我有一份人员名单'回答问卷。答案当前是一个字符串数组,所以我的对象看起来像
List<string[]> answers = new List<string[]>()
{ new string[]{"T","A","T","F","B"},
new string[]{"F","A","T","F","B"},
new string[]{"T","A","F","F","B"}
};
我需要找到所有值相同的数组索引和值。
生成的对象可以是string[]
,如
{"","A","","F","B"}
或某种类型的自定义对象元组,如{1,&#34; A&#34;},{3,&#34; F&#34;},{4,&#34; B&#34 ;}
我可以假设所有字符串数组的长度都相同。
我可以通过蛮力和循环来做到这一点,但我想知道是否有更有效的清洁方式,可能通过Linq。
这引出了一个问题,Linq是否只是在内部使用循环,唯一的效率是保存代码行并且必须创建局部变量。
更新 离开O. R. Mapper和Vajura 我在考虑两个循环
获取第一组答案,它给出了每个字符串[]的长度,并给出了答案应该是什么。即使第一个人是唯一一个回答A的人,那么所有其他非A将自动取消该指数的资格
for each index in string[]
answer = List[0][index]
for i=1 to List.Count - 1
compare answer to List[i][index]
if false exit loop
if we made it through it is good
答案 0 :(得分:6)
这样的事情应该有效:
answers
.SelectMany(x => x.Select((y, idx) => new { c = y, index = idx })) // 1
.GroupBy(x => x) // 2
.Where(x => x.Count() == answers.Count) // 3
.ToDictionary(x => x.Key.index, x => x.Key.c); // 4
这是工作fiddle
解释如下:
answer.Count
多个项目的组,所以我们确保所有内部数组中都存在字母索引对,换句话说:所有数组中相同索引处都出现一个字母答案 1 :(得分:1)
好吧,只是说你可以,这是一个Linq方法:
var results = answers.Aggregate(answers[0],(p, n) => p.Zip(n, (pi, ni) => pi==ni ? pi : "")
.ToArray())
.ToArray();
虽然如果你决定在一个真实的应用程序中使用它,我会清楚地记录它是如何工作的以及结果意味着什么。
实际上,这不会比设计合理的循环更有效,并且代码可读性更为简洁,所有其他条件都相同。
答案 2 :(得分:1)
LinQ中更简单的方法:
string[] result = answers
.Aggregate((a, b) =>
a.Select(a1 => (b[Array.IndexOf(a,a1)] == a1) ? a1 : "").ToArray());
如果您关心性能,我建议您在阵列上使用for
循环,因为它们比在List上执行foreach
快5倍(并且比Linq快很多) 。有一些关于它的文章,但我发现this非常有趣。另一方面,Linq更具可读性和优雅(好吧,这只是我的观点),所以如果您的阵列不是太长或者您不关心性能,我推荐您使用这种Linq方法。