将Lambda转换为嵌套for循环的Linq语句

本文关键字:循环 Linq 语句 for 嵌套 Lambda 转换 | 更新日期: 2023-09-27 17:53:48

是否有一种方法可以重写GetTransformedCollection方法,使其使用Linq语句而不是表达式?我目前正试图绕过"带语句体的lambda表达式不能转换为表达式树"错误。

public class Obj1
{
    public int Id { get; set; }
    public string[] Names { get; set; }
    public string[] Tags { get; set; }
}
public class EntCollections
{
    private List<Obj1> _results;
    [SetUp]
    public void SetUp()
    {
        _results = new List<Obj1>
        {
            new Obj1 {Id = 1, Names = new[] {"n1"}, Tags = new[] {"abc", "def"}},
            new Obj1 {Id = 2, Names = new[] {"n2", "n3"}, Tags = new[] {"ghi"}},
            new Obj1 {Id = 3, Names = new[] {"n1", "n3"}, Tags = new[] {"def", "xyz"}}
        };
    }
    private static Dictionary<string, List<string>>
        GetTransformedCollection(IEnumerable<Obj1> results)
    {
        var list = new Dictionary<string, List<string>>();
        foreach (var result in results)
        {
            foreach (var id in result.Names)
            {
                if (list.ContainsKey(id))
                {
                    list[id].AddRange(result.Tags);
                }
                else
                {
                    list.Add(id, result.Tags.ToList());
                }
            }
        }
        return list;
    }
    [Test]
    public void Test()
    {
        var list = GetTransformedCollection(_results);
        Assert.That(list["n1"], Is.EquivalentTo(new [] { "abc", "def", "def", "xyz" }));
        Assert.That(list["n2"], Is.EquivalentTo(new [] { "ghi" }));
        Assert.That(list["n3"], Is.EquivalentTo(new [] { "ghi", "def", "xyz" }));
    }

p。我不太担心结果类型是Dictionary,这只是将其表示为返回类型的最简单方法。

将Lambda转换为嵌套for循环的Linq语句

我个人会使用ILookup,这是一个很好的赌注,每当你有一个Dictionary<T1, List<T2>>,并与ToLookup()构建:

// Flatten the objects (lazily) to create a sequence of valid name/tag pairs
var pairs = from result in results
            from name in result.Names
            from tag in result.Tags
            select new { name, tag };
// Build a lookup from name to all tags with that name
var lookup = pairs.ToLookup(pair => pair.name, pair => pair.tag);

想法是先找到结果字典的所有键,然后从Obj1的原始序列中找到相应的值

var distinctNames = results.SelectMany(val => val.Names).Distinct();
return distinctNames
      .ToDictionary(name => name, 
                    name => results
                            .Where(res => res.Names.Contains(name))
                            .SelectMany(res => res.Tags)
                            .ToList());