英文:
How to merge a list of objects using LINQ
问题
我有一个定义如下的类
public class ResultClass()
{
public HashSet<string> VerifiedResults { get; private set; }
public HashSet<string> UnverifiedResults { get; private set; }
bool IsBlocked { get; private set; }
}
如果我有一个包含ResultClass项的列表,例如,List<ResultClass>()
,如何使用LINQ将结果合并为单个ResultClass对象。
是否有一种方法可以用LINQ代替我的下面的代码做到这一点?
var finalResult = new ResultClass();
foreach (var item in listOfResultClass)
{
finalResult.VerifiedResults.Union(item.VerifiedResults);
finalResult.UnverifiedResults.Union(item.UnverifiedResults);
finalResult.IsBlocked = item.IsBlocked;
}
英文:
I have a class defined below
public class ResultClass()
{
public HashSet<string> VerifiedResults { get; private set; }
public HashSet<string> UnverifiedResults { get; private set; }
bool IsBlocked {get; private set; }
}
If I have a list containing items for ResultClass, for eg., List<ResultClass>()
, how can I combine the results into a single ResultClass object using LINQ.
Is a way to do what my code below does, but with LINQ, instead?
var finalResult = new ResultClass();
foreach(var item in listOfResultClass)
{
finalResult.VerifiedResults.Union(item.VerifiedResults);
finalResult.UnverifiedResults.Union(item.UnverifiedResults);
finalResult.IsBlocked = item.IsBlocked;
}
答案1
得分: 2
这可以通过使用LINQ的Aggregate函数来实现,如下面的示例所示:
public class ResultClass
{
public HashSet<string> VerifiedResults { get; set; } = new();
public HashSet<string> UnverifiedResults { get; set; } = new();
public bool IsBlocked { get; set; } = false;
}
internal class Program
{
private static void Main()
{
var results = GetResults();
var finalResult = results.Aggregate(new ResultClass(), (r, next) =>
{
r.IsBlocked = r.IsBlocked || next.IsBlocked;
r.VerifiedResults.UnionWith(next.VerifiedResults);
r.UnverifiedResults.UnionWith(next.UnverifiedResults);
return r;
});
}
private static List<ResultClass> GetResults()
{
return new List<ResultClass>()
{
new ResultClass()
{
VerifiedResults = new HashSet<string>{"first", "second" },
UnverifiedResults = new HashSet<string>{"third" },
IsBlocked = false
},
new ResultClass()
{
VerifiedResults = new HashSet<string>{"first", "fourth" },
UnverifiedResults = new HashSet<string>{"fifth" },
IsBlocked = true
},
new ResultClass()
{
VerifiedResults = new HashSet<string> (),
UnverifiedResults = new HashSet<string>{"sixt", "seventh" },
IsBlocked = false
}
};
}
}
一些建议:
- 我修改了你的
ResultClass
以消除编译错误,并使其易于初始化列表。 - 对于
'IsBlocked'
属性,我使用了所有单独的IsBlocked
属性的逻辑OR。 - 在这种情况下,应该使用
UnionWith
而不是Union
。 - 可能需要考虑相同字符串出现在不同的
ResultClass
实例中,既在“已验证”属性中又在“未验证”属性中可能发生冲突。可能需要调整累加器lambda表达式以获得您想要的结果。
英文:
This can be achieved using the LINQ Aggregate function, as can be seen in following example:
public class ResultClass
{
public HashSet<string> VerifiedResults { get; set; } = new();
public HashSet<string> UnverifiedResults { get; set; } = new();
public bool IsBlocked { get; set; } = false;
}
internal class Program
{
private static void Main()
{
var results = GetResults();
var finalResult = results.Aggregate(new ResultClass(), (r, next) =>
{
r.IsBlocked = r.IsBlocked || next.IsBlocked;
r.VerifiedResults.UnionWith(next.VerifiedResults);
r.UnverifiedResults.UnionWith(next.UnverifiedResults);
return r;
});
}
private static List<ResultClass> GetResults()
{
return new List<ResultClass>()
{
new ResultClass()
{
VerifiedResults = new HashSet<string>{"first", "second" },
UnverifiedResults = new HashSet<string>{"third" },
IsBlocked = false
},
new ResultClass()
{
VerifiedResults = new HashSet<string>{"first", "fourth" },
UnverifiedResults = new HashSet<string>{"fifth" },
IsBlocked = true
},
new ResultClass()
{
VerifiedResults = new HashSet<string> (),
UnverifiedResults = new HashSet<string>{"sixt", "seventh" },
IsBlocked = false
}
};
}
}
A few remarks:
-
I adapted your
ResultClass
to remove compiler errors and to make it possible to initialize a list of them easily. -
for the
'IsBlocked
property, I used the logical OR of all the individualIsBlocked
properties. -
You should use
UnionWith
rather thanUnion
in this case. -
It might be a good idea to think about possible conflicts where the same string occurs in different
ResultClass
instances, both in 'verified' and 'unverified' properties. It may be necessary to adapt the accumulator lambda expression to get the results you want.
答案2
得分: 1
如@iSR5提到的,你可以使用 SelectMany
。我不确定你计划如何分配 IsBlocked
,但这似乎类似于你的代码:
var result = new ResultClass()
{
VerifiedResults = new HashSet<string>(results.SelectMany(x => x.VerifiedResults)),
UnverifiedResults = new HashSet<string>(results.SelectMany(x => x.UnverifiedResults)),
IsBlocked = results.LastOrDefault().IsBlocked,
};
另外,请阅读@Johan Donne的评论。
英文:
As @iSR5 mentioned, you can use SelectMany
. I am not sure how do you plan to assign the IsBlocked
, but this seems to behave like your code:
var result = new ResultClass()
{
VerifiedResults = new HashSet<string>(results.SelectMany(x => x.VerifiedResults)),
UnverifiedResults = new HashSet<string>(results.SelectMany(x => x.UnverifiedResults)),
IsBlocked = results.LastOrDefault().IsBlocked,
};
Also, please read @Johan Donne comments.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论