找到所有相同的答案

本文关键字:答案 | 更新日期: 2023-09-27 18:26:31

我有一份人们对问卷的回答列表。答案目前是一个字符串数组,所以我的对象看起来像

 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,"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

这是正在工作的fiddle

解释是:

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

好吧,只是说你可以,这里有一个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());

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