找到所有相同的答案

时间:2014-10-14 12:45:45

标签: c# arrays linq

我有一份人员名单'回答问卷。答案当前是一个字符串数组,所以我的对象看起来像

 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

3 个答案:

答案 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

解释如下:

  1. 展平列表并选择每个字母,并将其索引为匿名类型
  2. 按字母和索引分组(根据属性值比较匿名类型,因此我们按字母和索引同时进行分组)
  3. 这是一个棘手的部分,让那些拥有answer.Count多个项目的组,所以我们确保所有内部数组中都存在字母索引对,换句话说:所有数组中相同索引处都出现一个字母
  4. 最后将这些组放入一个字典,其中Keys是索引,值是字母。

答案 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方法。