-1

我想相互排他地捕获重复项,即我需要证明第一项和第三项都是重复项,并且第一项和第四项是重复项。

public class Foo
{
    public String Name { get; set; }
    public String SName { get; set; }
}

class Program
{
    static void Main(string[] args)
    {
        var list = new List<Foo>();
        list.Add(new Foo { Name = "a", SName = "d" });
        list.Add(new Foo { Name = "b", SName = "e" });
        list.Add(new Foo { Name = "c", SName = "a" });
        list.Add(new Foo { Name = "a", SName = "f" });

        // only groups by 1 name
        var duplicates = list.GroupBy(i => i.Name).Where(g => g.Count() > 1).Select(g => g.Key);
    }
}

我知道这可以用 foreach 轻松完成,我想学习。

4

4 回答 4

1

因此,我们将从任一列中获取所有重复的名称值开始,这相当容易:

IEnumerable<string> repeatedNames = list.SelectMany(foo => new[] { foo.Name, foo.SName })
    .GroupBy(name => name)
    .Where (g => g.Count () > 1)
    .Select(g => g.Key);

接下来,我们获取每个名称并找到包含该值的所有项目。最终结果是每个不同名称的序列,其中序列是Foo包含该值的所有项目。

IEnumerable<List<Foo>> groupings = repeatedNames .Select(name =>
    list.Where(foo => foo.Name == name || foo.SName == name).ToList());

如果您希望它不是 Foos 列表的序列,而是具有不同值和序列的项目序列,那么添加它很容易:

var groupings = repeatedNames .Select(name => new
    {
        Name = name,
        Foos = list.Where(foo => foo.Name == name || foo.SName == name).ToList()
    });
于 2012-10-24T20:11:08.467 回答
0

我想出了这个:

// Will return "a" - one which you already had
var duplicatesBetweenNames = list.GroupBy(i => i.Name)
    .Where(g => g.Count() > 1)
    .Select(g => g.Key).ToArray();

var duplicatedInSName = list.Select(x => x.Name)
    .Intersect(list.Select(x => x.SName));
// Will return "c" - represents Names where in SName is duplicate
var duplicatesBetweenNameAndSName = list
    .Where(f => duplicatedInSName.Contains(f.SName))
    .Select(x=>x.Name).ToArray();
于 2012-10-24T20:33:04.470 回答
0

如果您只想要重复的值,而不是它们出现的索引,那么您可以SelectMany在进行分组之前将名称转换为单个字符串列表:

var duplicates2 = list.SelectMany(n => new string[] {n.Name, n.SName})
                      .GroupBy(g => g)
                      .Where (g => g.Count () > 1)
                      .Select(g => g.Key)
                      .ToList();

编辑: 如果您想要Foo对象而不仅仅是字符串,您可以像这样选择它们:

var duplicates3 = list.Where(n => duplicates2.Contains(n.Name) ||
                                  duplicates2.Contains(n.SName));
于 2012-10-24T20:26:14.223 回答
0

有趣的线程,我只是认为在这种情况下查询语法非常有表现力:

var r = from l in list
        from s in new [] {l.Name,l.SName}
        group s by s into g
        where g.Count() > 1
        select g.Key into u
        from l in list
        where u.Contains(l.Name) || u.Contains(l.SName)
        select l;
于 2012-10-24T20:52:15.047 回答