我有两个学生姓名和考试成绩数组。
每个数组仅包含不同的学生(没有重复),其结构使arrStudentGroup1[0][0] = "Bob"
和arrStudentGroup1[0][1] = "98"
。
如果有两个数组,可以使用Intersect
创建arrStudentGroup1
和arrStudentGroup2
中存在的第三个学生数组吗?
我希望第三个数组有他们的名字和考试成绩。我该怎么做?
答案 0 :(得分:2)
如果你想只是两个组中的学生和不相关的考试成绩,只需在名字数组元素上相交:
var students1 = arrStudentGroup1.Select(group => group[0]);
var students2 = arrStudentGroup2.Select(group => group[0]);
var studentsInBoth = students1.Intersect(students2);
如果你还想要相关的测试分数,你需要实现一个比较每个数组的第一个元素的 IEqualityComparer<T>
。
如果您想要相关的测试分数,请加入两个数组:
var intersection = from s1 in arrStudentGroup1
join s2 in arrStudentGroup2 on s1[0] equals s2[0]
select new {Name = s1[0], Score1 = s1[1], Score2 = s2[1]}
foreach (var item in intersection)
{
Console.Writeline("{0}: s1={1}, s2={2}", Name, Score1, Score2);
}
答案 1 :(得分:0)
嗯,你可以这样做,
var studentsInGroup1 = arrStudentGroup1.Select(s => new
{
Name = s[0],
Score = s[1]
});
var studentsInGroup2 = arrStudentGroup2.Select(s => new
{
Name = s[0],
Score = s[1]
});
var studentsInBothGroups = studentsInGroup1.Join(
studentsInGroup2,
s => s.Name,
s => s.Name,
(one, two) => new
{
Name = one.Name,
Scores = new[] { one.Score, two.Score }
});
哪个应该为您提供一个方便的匿名类型,您可以像这样访问。
foreach(var student in studentsInBothGroups)
{
var Name = student.Name;
var Group1Score = student.Scores[0];
var Group2Score = student.Scores[1];
}
答案 2 :(得分:0)
将第一个zip(在一般意义上,而不是Zip
方法)数组转换为一个结构,将学生分组:
假设:
string[][] arrStudentGroup1 = new string[][]{new string[]{"Bob","98"}, new string[]{"Alice","98"}, new string[]{"Charles","78"}, new string[]{"Dariah","99"}};
string[][] arrStudentGroup2 = new string[][]{new string[]{"Bob","98"}, new string[]{"Fiona","98"}, new string[]{"Eve","78"}, new string[]{"Dariah","99"}};
然后:
var zipped1 = arrStudentGroup1.Select(student => new {Name = student[0], Score = student[1]});
var zipped2 = arrStudentGroup2.Select(student => new {Name = student[0], Score = student[1]});
现在得到十字路口。请注意,如果相同的学生姓名在一个但具有不同的分数,则不计为交集。这也可以解决,但我将你的问题解释为不想要那个案例。如果我读错了,请告诉我:
var inter = zipped1.Intersect(zipped2);
现在,您可以理想地使用它,或者甚至使用上面的new {Name = student[0], Score = int.Parse(student[1])}
并且使用数字而不是字符串(在大多数情况下更有用),坦率地说比处理数组数组更好,同时更加类型安全。不过,如果你真的想要它采用相同格式的字符串[]格式:
var interArray = inter.Select(st => new string[]{st.Name, st.Score});
如果你真的,真的希望整个事情采用相同的字符串[] []格式:
var interArrays = interArray.ToArray();
或者对于单行奇迹(大多数情况下可读性较差,但如果在同一方法中还有其他事情发生,有时将查询放在一行上会很好):
var interArrays = arrStudentGroup1
.Select(student => new {Name = student[0], Score = student[1]})
.Intersect(
arrStudentGroup2
.Select(student => new {Name = student[0], Score = student[1]})
).Select(st => new string[]{st.Name, st.Score}).ToArray()
输出:
{"Bob", "98"},{"Dariah", "99"}
编辑:或者,定义一个IEqualityComparer<string[]>
,如:
public class StudentComparer : IEqualityComparer<string[]>
{
public bool Equals(string[] x, string[] y)
{
if(ReferenceEquals(x, y))
return true;
if(x == null || y == null)
return false;
return x.SequenceEqual(y);
}
public int GetHashCode(string[] arr)
{
return arr == null ? 0 : arr.Select(s => s == null ? 0 : s.GetHashCode()).Aggregate((x, y) => x ^ y);
}
}
然后直接使用它:
var intersection = arrStudentGroup1.Intersect(arrStudentGroup2, new StudentComparer());
提供相同的输出。事实上更简单,但是当我看到数组被用作对象时,我的直觉就是尽快将它变成一个真实的对象,而且实际上,这并不是一种坏的本能 - 它也可以使其他更容易。