C# 找到所有相同的答案

C# 找到所有相同的答案,c#,arrays,linq,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"} }; 或者某种类型的自定义对象元组,类似于{1,“A”},{3,“F

我有一份人们对调查问卷的答案清单。答案当前是一个字符串数组,因此我的对象看起来像

 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"}
 };
或者某种类型的自定义对象元组,类似于{1,“A”},{3,“F”},{4,“B”}

我可以假设所有字符串数组的长度都相同

我可以通过蛮力和循环来做到这一点,但我想知道是否有一种更有效的更干净的方法,可能是通过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

像这样的方法应该会奏效:

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
这是工作票

解释如下:

  • 将列表展平,然后选择每个字母,并将其索引为匿名类型
  • 按字母和索引对这些对进行分组(根据属性值比较匿名类型,因此我们同时按字母和索引进行分组)
  • 这是一个棘手的部分,获取那些有
    答案的组。计算
    许多项,因此我们确保字母索引对存在于所有内部数组中,换句话说:所有数组中的同一索引处都存在一个字母
  • 最后,将这些组放入字典中,其中键是索引,值是字母

  • 像这样的方法应该会奏效:

    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
    
    这是工作票

    解释如下:

  • 将列表展平,然后选择每个字母,并将其索引为匿名类型
  • 按字母和索引对这些对进行分组(根据属性值比较匿名类型,因此我们同时按字母和索引进行分组)
  • 这是一个棘手的部分,获取那些有
    答案的组。计算
    许多项,因此我们确保字母索引对存在于所有内部数组中,换句话说:所有数组中的同一索引处都存在一个字母
  • 最后,将这些组放入字典中,其中键是索引,值是字母
  • 好吧,只是说你可以,这里有一个Linq方法:

    var results = answers.Aggregate(answers[0],(p, n) => p.Zip(n, (pi, ni) => pi==ni ? pi : "")
                                                          .ToArray())
                         .ToArray();
    
    虽然如果你决定在一个真正的应用程序中使用它,我会清楚地记录它是如何工作的以及结果意味着什么

    实际上,这并不比一个设计合理的循环更有效,代码可读性比简洁性更重要,在所有其他条件相同的情况下。

    好吧,只是说你可以,这里有一个Linq方法:

    var results = answers.Aggregate(answers[0],(p, n) => p.Zip(n, (pi, ni) => pi==ni ? pi : "")
                                                          .ToArray())
                         .ToArray();
    
    虽然如果你决定在一个真正的应用程序中使用它,我会清楚地记录它是如何工作的以及结果意味着什么


    实际上,这并不比一个设计合理的循环更有效,代码可读性比简洁性更重要,在其他条件相同的情况下。

    LinQ中更简单的方法是:

    string[] result = answers
          .Aggregate((a, b) => 
          a.Select(a1 => (b[Array.IndexOf(a,a1)] == a1) ? a1 : "").ToArray());
    

    如果您关心性能,我建议您对数组上的
    循环使用
    ,因为它们比在列表上执行
    foreach
    快5倍(也比Linq快得多)。有一些关于它的文章,但我觉得很有趣。另一方面,Linq更具可读性和优雅性(好吧,这只是我的观点),因此如果您的阵列不太长或者您不关心性能,我建议您使用这种Linq方法。

    Linq中一种更简单的方法:

    string[] result = answers
          .Aggregate((a, b) => 
          a.Select(a1 => (b[Array.IndexOf(a,a1)] == a1) ? a1 : "").ToArray());
    

    如果您关心性能,我建议您对数组上的
    循环使用
    ,因为它们比在列表上执行
    foreach
    快5倍(也比Linq快得多)。有一些关于它的文章,但我觉得很有趣。另一方面,Linq更具可读性和优雅性(好吧,这只是我的观点),因此,如果您的数组不是太长或者您不关心性能,我建议您使用这种Linq方法。

    Linq是一种语法糖,编译为IL时将在后台使用循环等。使用循环并不意味着使用暴力。而且,是的,LINQ只是在内部使用循环,因此与正确编写的循环相比,执行效率没有内在的提高。对于这个解决方案,除了“暴力”之外,没有其他方法。您需要检查每个值。也就是说,您可以对其进行大量优化,假设第二个字符串数组的第一个索引已经与第一个索引不同,那么您不需要再为任何后续数组检查该值。可能还有其他一些小事情可以优化它。@Vajura已经给出了两种不同的Linq方法,所以我不会说“暴力”是唯一的方法。这可能是最好的方法,但肯定不是唯一的方法。Linq是语法糖,当编译成IL时,将在后台使用循环等。使用循环并不意味着使用暴力。而且,是的,LINQ只是在内部使用循环,因此与正确编写的循环相比,执行效率没有内在的提高。对于这个解决方案,除了“暴力”之外,没有其他方法。您需要检查每个值。也就是说,您可以对其进行大量优化,假设第二个字符串数组的第一个索引已经与第一个索引不同,那么您不需要再为任何后续数组检查该值。可能还有其他一些小事情可以优化它。@Vajura已经给出了两种不同的Linq方法,所以我不会说“暴力”是唯一的方法。这可能是最好的方法,但肯定不是唯一的方法。谢谢你的失败。谢谢你的失败。