我有两个这样的列表:
public static List<List<List<double>>> listQ = new List<List<List<double>>>();
public static List<List<List<double>>> listVal = new List <List<List<double>>>();
2列表也有相同的大小。我想在listQ关系中对listVal进行一些操作:
例如:
listVal[0][0][ 1] = listVal[0][0][2] = 3.
所以,我希望listQ的索引相同。
(listQ[0][0][ 1] + listQ[0][0][2]) / 2 = (26.5 + 20.4) / 2 = 23.45.
现在,每个索引都必须有23.45:
listQ[0][0][ 1] = 23.45
listQ[0][0][ 2] = 23.45
同样;
listVal[0][2][0] = listVal[0][2][2] = 1
。因此,必须考虑listQ[0][2][0] and listQ[0][2][2]
的平均值。
我该怎么做?
编辑:@Roman Izosimov和@Petko Petkov的解决方案正常运作。哪一个有更高的性能?你怎么看?答案 0 :(得分:4)
lulz的LINQ解决方案:)
List<List<List<double>>> listVal = new List<List<List<double>>>(){
new List<List<double>>{
new List<double>(){1,1,3},
new List<double>(){2,1,2},
new List<double>(){1,2,3}
},
new List<List<double>>{
new List<double>(){2,1,3},
new List<double>(){2,4,2},
new List<double>(){3,1,3}
},
new List<List<double>>{
new List<double>(){4,1,1},
new List<double>(){4,2,1},
new List<double>(){4,3,1}
}
};
List<List<List<double>>> listQ = new List<List<List<double>>>(){
new List<List<double>>{
new List<double>(){3,7,4},
new List<double>(){8,15,23},
new List<double>(){11,13,17}
},
new List<List<double>>{
new List<double>(){90,3,7},
new List<double>(){5,7,12},
new List<double>(){7,14,21}
},
new List<List<double>>{
new List<double>(){32,4,1},
new List<double>(){55,12,8},
new List<double>(){3,5,8}
}
};
//Linq awesomeness
var qry = listVal.SelectMany((l1, i0) =>
l1.SelectMany((l2, i1) =>
l2.Select((ele, i2) =>
new { i0, i1, i2, gVal = ele, qVal = listQ[i0][i1][i2] })))
.GroupBy(x => new { x.i0, x.i1, x.gVal }) // if you want to average across the innermost lists only
//.GroupBy(x => x.gVal) //if you want to average acreoss the whole data
.SelectMany(x => x.Select(e => new { e.i0, e.i1, e.i2, avg = x.Average(y => y.qVal) }));
foreach (var e in qry)
{
listQ[e.i0][e.i1][e.i2] = e.avg;
}
答案 1 :(得分:3)
您的问题类似于计算列表中元素的频率
您可以使用Dictionary<double,List<int[]>
double
键是listVal中的值,List<int[]>
将该值的位置存储在listVal中。
这是我的示例代码:
//we store list of indices with the same value in a dictionary
Dictionary<double, List<int[]>> dictionary = new Dictionary<double, List<int[]>>();
//loop over listVal
for (int i = 0; i < listVal.Count; i++)
for (int j = 0; j < listVal[i].Count; j++)
for (int k = 0; k < listVal[i][j].Count; k++)
{
if (!dictionary.ContainsKey(listVal[i][j][k]))
{
//if the dictionary doesn't have value listVal[i][j][k]
//then add the value as key with the value's current index
dictionary.Add(listVal[i][j][k], new List<int[]> { new int[] { i, j, k } });
}
else
{
//add more index of the same value to the index list
dictionary[listVal[i][j][k]].Add(new int[] { i, j, k });
}
}
foreach (var entry in dictionary)
{
//get list of all position having the same value
List<int[]> indices = entry.Value;
//do your process on listQ
//sum values in listQ
double sum = 0;
foreach (var index in indices)
{
sum += listQ[index[0]][index[1]][index[2]];
}
//calculate average value
double average = sum / indices.Count;
//assign back to litsQ
foreach (var index in indices)
{
listQ[index[0]][index[1]][index[2]] = average;
}
}
答案 2 :(得分:3)
在我的解决方案中,您可以在List<double>
和listQ
listVal
中包含任意数量的元素,但在这两个列表中,元素数量相同。
算法:
for (var i1 = 0; i1 < listVal.Count; i1++)
for (var i2 = 0; i2 < listVal[i1].Count; i2++)
{
var alreadyInList = new Dictionary<double, List<Tuple<int, int, int>>>();
for (var d = 0; d < listVal[i1][i2].Count; d++)
{
var decVal = listVal[i1][i2][d];
if (!alreadyInList.ContainsKey(decVal))
{
alreadyInList.Add(decVal, new List<Tuple<int, int, int>>());
continue;
}
var firstMatchElIndex = listVal[i1][i2].IndexOf(decVal);
if (alreadyInList[decVal].All(x => x.Item3 != firstMatchElIndex))
alreadyInList[decVal].Add(new Tuple<int, int, int>(i1, i2, firstMatchElIndex));
alreadyInList[decVal].Add(new Tuple<int, int, int>(i1, i2, d));
}
SetListQ(listQ, alreadyInList.Where(x => x.Value.Count > 1).Select(x => x.Value));
}
private void SetListQ(List<List<List<double>>> listQ, IEnumerable<List<Tuple<int, int, int>>> matches)
{
foreach (var match in matches)
{
var sum = match.Sum(tuple => listQ[tuple.Item1][tuple.Item2][tuple.Item3]);
var avg = sum / match.Count;
foreach (var tuple in match)
listQ[tuple.Item1][tuple.Item2][tuple.Item3] = avg;
}
}
并检查:
Console.WriteLine("listQ[0][0][0] = {0}", listQ[0][0][0]);
Console.WriteLine("listQ[0][0][1] = {0}", listQ[0][0][1]);
Console.WriteLine("listQ[0][0][2] = {0}", listQ[0][0][2]);
//....
使用您的数据:
var listQ = new List<List<List<double>>>
{
new List<List<double>>
{
new List<double>{20.9, 26.5, 20.4},
new List<double>{18.3, 19.7, 22.2},
new List<double>{12.7, 20.6, 25.6},
new List<double>{17.1},
new List<double>{17.3},
new List<double>{16.9}
}
};
var listVal = new List<List<List<double>>>
{
new List<List<double>>
{
new List<double>{1, 3, 3},
new List<double>{1, 3, 3},
new List<double>{1, 3, 1},
new List<double>{1},
new List<double>{3},
new List<double>{3}
}
};
我们在控制台中:
listQ[0][0][0] = 20.9
listQ[0][0][1] = 23.45
listQ[0][0][2] = 23.45
listQ[0][1][0] = 18.3
listQ[0][1][1] = 20.95
listQ[0][1][2] = 20.95
listQ[0][2][0] = 19.15
listQ[0][2][1] = 20.6
listQ[0][2][2] = 19.15
例如,我添加了一些额外的数据:
var listQ = new List<List<List<double>>>
{
new List<List<double>>
{
new List<double>{20.9, 26.5, 20.4, 10.0},
new List<double>{18.3, 19.7, 22.2, 12.22},
new List<double>{12.7, 20.6, 25.6, 20.6},
new List<double>{17.1},
new List<double>{17.3},
new List<double>{16.9}
}
};
var listVal = new List<List<List<double>>>
{
new List<List<double>>
{
new List<double>{1, 3, 3, 1},
new List<double>{1, 3, 3, 3},
new List<double>{1, 3, 1, 2},
new List<double>{1},
new List<double>{3},
new List<double>{3}
}
};
处理完毕后我们有:
listQ[0][0][0] = 15.45
listQ[0][0][1] = 23.45
listQ[0][0][2] = 23.45
listQ[0][0][3] = 15.45
listQ[0][1][0] = 18.3
listQ[0][1][1] = 18.04
listQ[0][1][2] = 18.04
listQ[0][1][3] = 18.04
listQ[0][2][0] = 19.15
listQ[0][2][1] = 20.6
listQ[0][2][2] = 19.15
listQ[0][2][3] = 20.6
这不是一个很好的解决方案,但它可以工作并使用最少的迭代次数。我希望这个解决方案能够解决你的任务。