找到所有相同的答案
本文关键字:答案 | 更新日期: 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
解释是:
- 将列表展平,选择每个字母,并将其索引为匿名类型
- 按字母和索引分组(根据属性值比较匿名类型,因此我们同时按字母和指数分组)
- 这是棘手的部分,让那些具有
answer.Count
多个项的组,所以我们确保字母索引对存在于所有内部数组中,换句话说:一个字母存在于所有数组中的同一索引处 - 最后将这些组放入字典中,其中键是索引,值是字母
好吧,只是说你可以,这里有一个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方法。