2011-11-01 86 views
3

我對這個頁面不熟悉,對編程也很陌生。
讓我提出我的問題。 我有一個數組假設查找C中行元素之間的區別#

1 2 3 

4 5 6 

7 8 9 

3 2 1 

我想要做的是計算每一行的所有要素間的差異。

{Math.Abs(1-2)=1 

Math.Abs (2-3)=1 

Math.Abs (1-3)=2} 

第一行。接下來,我想找到每行的平均值(在第一個(1 + 1 + 2)/ 3)中,並最終保持該行的最小平均值。

什麼是最有效的方法?(我認爲perphaps LINQ可以工作,但我不知道如何正確使用LINQ)。 任何幫助,將不勝感激。 謝謝大家提前!

編輯: 謝謝大家的答案...有真正有用的,並幫助我瞭解我應該如何處理我的問題。我發現大多數人都推薦使用List。所以這給我提出了另一個問題(記住一點編程知識)如何將一個int [,]數組轉換爲List,這是可能的?我應該先將int [,]轉換爲int [] [],然後再轉換爲List? 再次感謝您的回答和您的時間。

我創建了以下功能的二維數組轉換爲List..but看來它不工作properly..Any幫助,將真正的讚賞..

public static List<int[]> GetMyNumbers(int[,] result) 
    { 

     int[,] res = result; 

     int length = res.GetUpperBound(0) + 1; 
     int width = res.GetUpperBound(1) + 1; 
     int[] rows = new int[width]; 
     List<int[]> numberArrays = new List<int[]>(); 

     for (int i = 0; i < result.Length/width; i++) 
     { 
      for (int k = 0; k < width; k++) 
      { 
       rows[k] = res[i, k]; 
       Console.Write(rows[k]); 
      } 
      Console.WriteLine(); 
      numberArrays.Add(rows);//this doesn't fill the list properly..It adds to all list items the last row of the 2d array 

     } 

     return numberArrays; 


    } 
+0

如果你放棄所有比一個具有最低平均等其他行,你需要計算他們的區別是什麼?如果不是,有效的方法是首先丟棄行,然後制定出你已經離開了1排的差異,差異將更加耗時比平均值(或者至少,這取決於有多少項目是在行是)。 – AndrewC

+0

可能我沒有提出足夠清晰的問題。我想要做的是計算每條線的差值的平均值.. – tasos

+0

@tasos好了,所以我在正確認識你,你只是想通過每一行,然後計算出的差異發現每行的平均差異? – Purplegoldfish

回答

1

這裏是你在找什麼根本。不,我沒有測試代碼,以確保它是100%正確的,但應該讓你至少朝着正確的方向前進。

// Look, a two dimensional version. 
    int[][] numberArray = GetMyNumbers(); 

    // Placeholder for the lowest averge/corresponding index. 
    double lowestAvg = double.MaxValue; 
    int lowestIndex = -1; 

    for (int rowIndex = 0; rowIndex < numberArray.Length; rowIndex++) 
    { 

    { 
     int[] row = numberArray[rowIndex]; 
     int n = row.Length; 
     int[] diffs = new int[(n * n) - n]; 

     // Get all of the differences. 
     int count = 0; 
     for (int i = 0; i < n; i++) 
     { 
     for (int j = i + 1; j < n; j++) 
     { 
      diffs[count] = Math.Abs(row[i] - row[j]); 
      count++; 
     } 
     } 

     // Average them.. 
     double sum = 0; 
     for (int i = 0; i < diffs.Length; i++) 
     { 
     sum += diffs[i]; 
     } 
     double avg = sum/diffs.Length; 

     // Compare to the lowest value, making note of a new low. 
     if (avg < lowestAvg) 
     { 
     lowestAvg = avg; 
     lowestIndex = rowIndex; 
     } 
    } 

    } 

    // Now that we are here, we know which index has the lowest average of differences. 
    // Do whatever you want with it. 
    int[] TheAnswer = numberArray[lowestIndex]; 
+0

非常感謝你的答案..但我怎麼能將int [,]數組轉換爲列表? beacause .ToList方法不起作用或Cast.ToList ... – tasos

+0

那裏,現在它使用了一個2D數組。 –

1

如果我要解決這個問題我會改變你的數據存儲方式。

首先,我將創建一個名爲myNumbers(或其他)的新類,該類必須包含一個整數數組和一個名爲average的屬性,並且只有一個get方法(您不希望能夠手動更改此值。您也可以創建一個構造函數,該構造函數接受創建類的新實例時要使用的整數數組(此新類表示您當前擁有的數組中的一行)

您的屬性名爲average將會是一個int,它會循環遍歷數組並計算出平均值然後返回它。

http://msdn.microsoft.com/en-us/library/aa288470(v=vs.71).aspx C#屬性教程。

現在在你想要擺脫數組的主代碼中,改爲創建一個List,並用你的myNumbers類的新實例填充它。

現在,您只需爲每個循環創建一個並瀏覽列表,即可檢查列表中每個項目的平均屬性以獲取平均值,或者可以完全忽略該循環,並使用LINQ選擇最高值

http://msdn.microsoft.com/en-us/library/bb383799(v=vs.90).aspx的LINQ教程(有很多更在網絡上)

我覺得上面的形式給出將滿足您的需求最好的,因爲你需要存儲的平均值等,它也給你一些做法與類/屬性/循環/列表等,因爲你是編程新手。

如果你有一些代碼,仍然奮鬥請在這裏更新您的文章,我們會盡力幫助。我以爲我會先不用代碼來回答這個問題,所以至少你可以自己去做,等等。

+0

非常感謝你我會研究你提供的鏈接,並回來... – tasos

+0

@ tasos祝你好運!當你完成後發佈你的代碼,並確定人們會願意建議改進等:)並歡迎來到SO – Purplegoldfish

2

這是非常簡陋,但希望你可以從這個。基本上,它將鋸齒陣列轉換爲陣列列表,然後用單獨的方法計算出平均值,並將結果按平均值排序並取1。

值得關注的是我的解決方案總是試圖存儲差的正值(因爲這似乎是你在做什麼),即代替1個3捐贈-2它給2.

我相信有一種更清潔的方式來創建這個解決方案,但這是我現在可以提出的最好的方法。

static void Main(string[] args) 
     { 
      int[][] multi = new int[3][]; 
      multi[0] = new int[3] { 1, 2, 3 }; 
      multi[1] = new int[3] { 5, 10, 20 }; 
      multi[2] = new int[3] { 3, 4, 8 }; 
      List<int[]> t = multi.ToList(); 
      List<int[]> avg = t.OrderBy(x => GetAvgDifference(x)).Take(1).ToList(); 
     } 

     public static double GetAvgDifference(int[] arr) 
     { 
      List<int> differences = new List<int>(); 
      for (int i = 0; i < arr.Length; i++) 
      { 
       for (int j = i; j < arr.Length; j++) 
       { 
        int difference = arr[i] - arr[j]; 

        if (difference < 1) 
        { 
         differences.Add(difference * -1); 
        } 
        else 
        { 
         differences.Add(difference); 
        } 
       } 
      } 

      return differences.Average(); 
     } 
+0

我試圖通過在這裏給出的所有解決方案,因爲我是新手我有問題。如果我理解你的解決方案,你建議將值傳遞給鋸齒陣列,然後將其轉換爲列表並處理列表。我的問題是數組是另一個函數的輸出,我不知道數組的大小。我試圖通過網絡找到我能做些什麼來將int [,]數組轉換爲列表,但我沒有找到有效的工作..有任何建議? – tasos

1

試試這個

var rows = new List<List<int>>(){ 
      new List<int>(){1, 2, 3}, 
      new List<int>(){4, 5, 6}, 
      new List<int>(){7, 8, 9}, 
      new List<int>(){3, 2, 1}}; 

    var averages = new List<double>(); 
    foreach(var list in rows) 
    { 
     var diffs = new List<int>(); 
     for (int i = 0; i < list.Count - 1; i++) 
      for (int j = i+1; j < list.Count; j++) 
       diffs.Add(Math.Abs(list[i]-list[j])); 
     averages.Add(diffs.Average()); 
    } 
    averages.ForEach(i=>Console.WriteLine(i)); 
    Console.WriteLine("Minimum average is " + averages.Min()); 

您的所有視頻片段都以類似的方式不同,因此在本例中的所有均線將是1.3333

2

您可以在陣列上使用LINQ這樣只有一行:

int[] tab = { 1, 2, 3 }; 
var tuples = tab.Select((number, index) => new Tuple<int, int>(index, number)); 
var average = tuples.SelectMany(t => tuples.Where(current => current.Item1 > t.Item1), (t1, t2) => Math.Abs(t1.Item2 - t2.Item2)).Average(); 

你剛纔相同的應用到您的陣列中的所有行,然後使用MIN()擴展方法。

1

如果性能真的很重要,請考慮使用存儲行的 平坦int數組(您沒有List<int>的內存開銷)。 然後,通過將行長度遞增 您的當前索引扁平陣列上進行迭代,然後計算平均值爲 當前行。

這裏是一個小例子:

int rowLen = 3; 
int numberOfRows = 3; 
int[] rowValues = new int[rowLen * numberOfRows]; 

float[] avgs = new float[numberOfRows]; 

// First row 
rowValues[0] = 1; 
rowValues[1] = 2; 
rowValues[2] = 3; 

// Second row 
rowValues[3] = 6; 
rowValues[4] = 5; 
rowValues[5] = 6; 

// Third row 
rowValues[6] = 7; 
rowValues[7] = 8; 
rowValues[8] = 9; 

float currMinAvg = float.MaxValue; 
int minIdx = -1; 
int currRow = 0; 
for (int i = 0; i <= numberOfRows * rowLen - rowLen; i += rowLen) 
{  
    avgs[currRow] = 0; 
    int c = 0; 
    for (int k = i; k < i + rowLen-1; k++) 
    { 
    for (int p = k + 1; p < i + rowLen; p++) 
    { 
     c++; 
     //Console.Out.WriteLine("calc: rowValues[{0}] - rowValues[{1}]", k, p); 
     avgs[currRow] += Math.Abs(rowValues[k] - rowValues[p]); 
    } 
    } 

    //Console.Out.WriteLine(avgs[currRow]); 
    avgs[currRow] /= c; 

    if (avgs[currRow] < currMinAvg) 
    { 
    minIdx = i; 
    currMinAvg = avgs[currRow]; 
    } 
    currRow++; 
} 

Console.Out.WriteLine("Min row indexs: {0}, min average = {1}", minIdx, currMinAvg); 

注意,上面的碼被優化性能。它很明顯傷害可讀性

希望,這有助於。

1

下面是一些代碼有一些意見,我做怪異的東西。我想你已經有很多有趣的答案,但我沒有看到任何簡單的事情,所以這是我的嘗試。

static void Main(string[] args) 
{ 
    // quickest way to initialize your input 
    var input = new int[][]{ 
     new int[]{1, 2, 3}, 
     new int[]{4, 5, 6}, 
     new int[]{7, 8, 9}, 
     new int[]{3, 2, 1} 
    }; 

    /* to get the average, 
    * 1. add up all the differences 
    * 2. divide by m choose 2 where m is the length of a row 
    */ 

    // helpful factorial functoid 
    Func<int, int> factorial = null; 
    factorial = (n => (n > 1) ? n * factorial(n - 1) : 1); 
    var mChoose2 = factorial(input[0].Length)/(2 * factorial(input[0].Length - 2)); 

    var getAverageOfDifferencesFunctoid = new Func<int[], double>(
     row => row.Select(
      (number1, indexInRow1) => row.Select(
       (number2, indexInRow2) => indexInRow2 > indexInRow1 ? Math.Abs(number1 - number2) : 0 
       // add up all the differences for number1 with the rest of the array 
      ).Sum() 
     // add up all the sums of all the differences 
     ).Sum() 
     // divide by the number of differences 
     /(double)mChoose2 
    ); 

    // use the functoid defined above to calculate the average of differences for each row and pick the minimum 
    Console.WriteLine(input.Select(row => getAverageOfDifferencesFunctoid(row)).Min()); 
} 
1
double[,] A = { { 1, 2, 3 }, { 4, 5, 6 } , { ... } ... }; 
// Initialize array of averages 
double[] R = new double[N] // N is number of rows 
// Calculate averages for each row 
for(int i=0; i<N; i++) 
{ 
    R[i] = (Math.Abs(A[i,0]-A[i,1])+Math.Abs(A[i,1]-A[i,2])+Math.Abs(A[i,2]-A[i,0]))/3; 
} 
// Find the best value 
double R_min = R.Max(); 
// Find the index where values equals the min. 
int k = R.Select((r, i) => r == R_min ? i : N).Min(); 
// Now A[k,*] contains the values you want to keep. 
+0

非常感謝你的解決方案..但我發佈的數組是一個例子,不幸的是我不知道數組A [i,j]的列數或行數。所以我正在尋找適用於不同尺寸陣列的東西。但再次感謝.. – tasos

+0

然後使用'N = A.GetLength(0)'查找行數。 – ja72

相關問題