我是这个页面的新手,也是编程新手。
让我提出我的问题。
我有一个数组让我们说
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吗? 再一次感谢您的回答和时间。
我创建了以下函数,用于将2d数组转换为List ..但它似乎无法正常工作..任何帮助都会真正受到赞赏..
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 :(得分:2)
这非常粗糙,但希望你可以从中获取。基本上,它将您的锯齿状数组转换为数组列表,然后以单独的方法计算平均值,并按平均值排序结果并取一个。
值得注意的是,我的解决方案总是试图存储差异的正值(因为这似乎是你正在做的事情),即代替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();
}
答案 1 :(得分: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()扩展方法。
答案 2 :(得分:1)
如果我要解决这个问题,我会改变数据的存储方式。
首先,我将创建一个名为myNumbers(或其他)的新类,此类必须包含一个整数数组和一个名为average的属性,仅使用get方法(您不希望能够手动更改此值。也可以创建一个构造函数,它接受在创建类的新实例时要使用的整数数组。(这个新类代表你当前拥有的数组中的1行)
你的名为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教程(网上还有更多内容)
我认为上述方法最适合您的需求,因为您需要存储平均值等。它还为您提供了类/属性/循环/列表等的练习,因为您不熟悉编程。
如果你有一些代码并且还在努力,请在此处更新您的帖子,我们会尽力提供帮助。我想我会在没有代码的情况下回答这个问题,所以至少你可以自己动手做等等。
答案 3 :(得分: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
答案 4 :(得分: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];
答案 5 :(得分:1)
如果性能真的很重要,请考虑使用flat 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);
请注意,上面的代码针对性能进行了优化。它显然伤害了可读性。
希望,这有帮助。
答案 6 :(得分: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());
}
答案 7 :(得分: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.