如何从子查询中引用父LINQ查询

时间:2019-04-22 21:30:06

标签: c# .net linq

我正在尝试开发一个LINQ查询,该查询将标识具有重复值的对象。我只需要多值属性中的字符串与另一个对象中相同属性中的字符串匹配且“名称”值不匹配的对象。

我正在尝试使用以下代码,但由于无法在子查询中使用“ o”变量,因此无法正常工作。

myList.Where(o => myList.Any(a => a.name != o.name && a.multival.Any(p => o.multival.Contains(p))))

2 个答案:

答案 0 :(得分:1)

为什么还要为此使用linq?它会令人费解,难以阅读。我将使用嵌套的for循环解决此问题:

var listOfDuplicates = new IEnumerable<YourObjectType>();
foreach (var a in myList)
{
     foreach (var b in myListb)
     {
         if (a.multival == b.multival && a.name != b.name)
             listOfDuplicates.Add(a);
     }
}

作为对评论的回应,这是一种实现类似于LINQs FirstOrDefault()的退出方法以及其他X次匹配后退出的方法的方法:

Public IEnumerable<YourObjectType> FindDuplicates(IEnumerable<YourObjectType> myList, int maxDupes)
{
    var listOfDuplicates = new IEnumerable<YourObjectType>();
    foreach (var a in myList)
    {
        foreach (var b in myListb)
        {
            if (a.multival == b.multival && a.name != b.name)
                listOfDuplicates.Add(a);
            if (listOfDuplicates.length == maxDupes)
                return listOfDuplicates;
        }
    }
    return listOfDuplicates;
}

答案 1 :(得分:-1)

您的查询实际上应该“有效”,但是如果您的列表大小特别大,效率将不高。如果您在编译时遇到麻烦,请检查以确保没有错别字。如果您在运行时遇到问题,请对变量和属性添加一些null检查。该答案的其余部分将指导您如何利用Linq改进查询。

考虑到您尝试编写的查询,尽管我为“ multival”使用了不同的名称,但我将推断以下内容与类结构的相关部分非常接近。

class Foo 
{
    public string Name { get; set; }
    public string[] Attributes { get; set; }
}

然后给出一个大致像这样的对象列表

var mylist = new List<Foo>
{
    new Foo { Name = "Alpha", Attributes = new[] { "A", "B", "C" } },
    new Foo { Name = "Bravo", Attributes = new[] { "D", "E", "F" } },
    new Foo { Name = "Charlie", Attributes = new[] { "G", "H", "A" } }
};

要基于属性的 any 匹配查找与任何其他对象匹配的对象,这就是我使用Linq处理它的方式:

var part1 = from item in mylist 
            from value in item.Attributes 
            select new { item, value };

var query = (from pairA in part1
            join pairB in part1 on pairA.value equals pairB.value
            where pairA.item.Name != pairB.item.Name
            select pairA.item)
            .Distinct(); // ToList() to materialize, as necessary

如果要通过选择的编辑器运行该代码并浏览part2的内容,则可能希望看到基于“ A”共享属性的对象“ Alpha”和“ Charlie”。

如果初始列表的大小很大(例如,列表包含10,000个元素而不是3个元素),则此方法应比嵌套的foreach更好地扩展,这正是您的初始方法。