我需要能够仅返回具有唯一AccessionNumber的记录及其对应的LoginId。最后,数据看起来像是:
然而,我的问题在于这行代码,因为Distinct()返回一个IEnumerable字符串而不是IEnumerable of string []。因此,编译器抱怨字符串不包含AccessionNumber和LoginId的定义。
yield return new[] { record.AccessionNumber, record.LoginId };
这是我要执行的代码:
internal static IEnumerable<string[]> GetTestDataForSpecificItemType(ItemTypes itemTypeCode)
{
IEnumerable<StudentAssessmentTestData> data = DataGetter.GetTestData("MyTestData");
data = data.Where(x => x.ItemTypeCode.Trim() == itemTypeCode.ToString());
var z = data.Select(x => x.AccessionNumber).Distinct();
foreach (var record in z)
{
yield return new[] { record.AccessionNumber, record.LoginId };
}
}
答案 0 :(得分:0)
这是因为您只通过以下
选择了该属性AccessionNumber
var z = data.Select(x => x.AccessionNumber).Distinct();
您可能想要选择整个StudentAssessmentTestData
记录
data = data.Where(x => x.ItemTypeCode.Trim() == itemTypeCode.ToString()).Distinct();
foreach (var record in data)
{
yield return new[] { record.AccessionNumber, record.LoginId };
}
答案 1 :(得分:0)
不使用Distinct
,而是使用GroupBy
。这样:
var z = data.Select(x => x.AccessionNumber).Distinct();
foreach (var record in z)
{
yield return new[] { record.AccessionNumber, record.LoginId };
}
应该是这样的:
return data.GroupBy(x => x.AccessionNumber)
.Select(r => new { AccessionNumber = r.Key, r.First().LoginId});
GroupBy()
调用仅确保AccessionNumber
的唯一条目,而First()
确保只返回带有LoginId
的第一个AccessionNumber
。
这假定您的数据的排序方式是,如果有多个登录具有相同的AccessionNumber,则第一次登录是正确的。
答案 2 :(得分:0)
如果您想根据特定属性选择不同的值,可以通过多种方式进行。
如果它总是与您希望用于比较的属性相同,则可以覆盖Equals
类中的GetHashCode
和StudentAssessmentTestData
方法,从而允许使用Distinct
方法为了识别这些类是如何彼此不同的,可以在这个question
但是,您也可以为您的实现实现自定义IEqualityComparer<T>
,例如以下版本
// Custom comparer taking generic input parameter and a delegate function to do matching
public class CustomComparer<T> : IEqualityComparer<T> {
private readonly Func<T, object> _match;
public CustomComparer(Func<T, object> match) {
_match = match;
}
// tries to match both argument its return values against eachother
public bool Equals(T data1, T data2) {
return object.Equals(_match(data1), _match(data2));
}
// overly simplistic implementation
public int GetHashCode(T data) {
var matchValue = _match(data);
if (matchValue == null) {
return 42.GetHashCode();
}
return matchValue.GetHashCode();
}
}
然后可以将此类用作Distinct
函数的参数,例如以这种方式
// compare by access number
var accessComparer = new CustomComparer<StudentTestData>(d => d.AccessionNumber );
// compare by login id
var loginComparer = new CustomComparer<StudentTestData>(d => d.LoginId );
foreach (var d in data.Distinct( accessComparer )) {
Console.WriteLine( "{0}, {1}", d.AccessionNumber, d.LoginId);
}
foreach (var d in data.Distinct( loginComparer )) {
Console.WriteLine( "{0}, {1}", d.AccessionNumber, d.LoginId);
}
您可以在此dotnetfiddle
中找到完整示例答案 3 :(得分:0)
添加LinqExtension方法DistinctBy,如下所示。
public static class LinqExtensions
{
public static IEnumerable<TSource> DistinctBy<TSource, TKey>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector)
{
HashSet<TKey> seenKeys = new HashSet<TKey>();
foreach (TSource element in source)
{
if (seenKeys.Add(keySelector(element)))
{
yield return element;
}
}
}
}
在你的代码中使用它:
var z = data.DistinctBy(x =&gt; x.AccessionNumber);
internal static IEnumerable<string[]> GetTestDataForSpecificItemType(ItemTypes itemTypeCode)
{
IEnumerable<StudentAssessmentTestData> data = DataGetter.GetTestData("MyTestData");
data = data.Where(x => x.ItemTypeCode.Trim() == itemTypeCode.ToString());
var z = data.DistinctBy(x => x.AccessionNumber);
foreach (var record in z)
{
yield return new[] { record.AccessionNumber, record.LoginId };
}
}
答案 4 :(得分:0)
这是最终有效的代码:
internal static IEnumerable<string[]> GetTestDataForSpecificItemType(ItemTypes itemTypeCode)
{
var data = DataGetter.GetTestData("MyTestData");
data = data.Where(x => x.ItemTypeCode.Trim() == itemTypeCode.ToString());
var z = data.GroupBy(x => new{x.AccessionNumber})
.Select(x => new StudentAssessmentTestData(){ AccessionNumber = x.Key.AccessionNumber, LoginId = x.FirstOrDefault().LoginId});
foreach (var record in z)
{
yield return new[] { record.AccessionNumber, record.LoginId };
}
}
返回类似于此的序列:
答案 5 :(得分:0)
你可以试试这个。它对我有用。
IEnumerable<StudentAssessmentTestData> data = DataGetter.GetTestData("MyTestData");
data = data.Where(x => x.ItemTypeCode.Trim() == itemTypeCode.ToString());
var z = data.GroupBy(x => x.AccessionNumber).SelectMany(y => y.Take(1));
foreach (var record in z)
{
yield return new[] { record.AccessionNumber, record.LoginId };
}
答案 6 :(得分:0)
我不是100%肯定你在问什么。您要么(1)只有具有唯一AccessionNumber
的记录,如果两个或多个记录具有相同的AccessionNumber
,则不返回它们,或者(2)只有每个AccessionNumber的第一个记录。 / p>
以下是两个选项:
(1)
internal static IEnumerable<string[]> GetTestDataForSpecificItemType(ItemTypes itemTypeCode)
{
return
DataGetter
.GetTestData("MyTestData");
.Where(x => x.ItemTypeCode.Trim() == itemTypeCode.ToString())
.GroupBy(x => x.AccessionNumber)
.Where(x => !x.Skip(1).Any())
.SelectMany(x => x)
.Select(x => new [] { x.AccessionNumber, x.LoginId });
}
(2)
internal static IEnumerable<string[]> GetTestDataForSpecificItemType(ItemTypes itemTypeCode)
{
return
DataGetter
.GetTestData("MyTestData");
.Where(x => x.ItemTypeCode.Trim() == itemTypeCode.ToString())
.GroupBy(x => x.AccessionNumber)
.SelectMany(x => x.Take(1))
.Select(x => new [] { x.AccessionNumber, x.LoginId });
}