0

我有一个包含几条记录的数据行的 newLinks 集合。这是表结构

LinkSysId | LinkId | Col1 | Col2
1           1        str    str1
2           1        str5   str4 
3           2        str2   str3
4           2        str6   str7

我想做一个 linq 查询,它会迭代集合并只留下前 1 个不同的 LinkId 记录:

LinkSysId | LinkId | Col1 | Col2
1           1        str    str 
3           2        str3   str3

我试着做这样

newLinks.RemoveAll(rowComp => newLinks.Any(rowDel => 
                   rowComp["linkId"].ToString() == rowDel["linkId"].ToString() 
                   &&  rowComp["linkSysId"].ToString() != rowDel["linkSysId"].ToString()));

但它会从集合中删除所有项目?谢谢你的帮助

4

3 回答 3

3

有实现 DistinctBy() 的 LINQ 扩展库,这正是您正在寻找的。然而,这个小片段利用了这样一个事实:如果已经添加了相同的项目,则 hashset 上的 Add() 方法返回 false:

var foundIds = new HashSet<int>();
var FirstLinkId = newLinks.Where(row=>foundIds.Add(row.LinkId)).ToList();
于 2013-03-21T13:34:39.397 回答
1

正如 Tormod 所说,最好的方法是使用DistinctBy()实​​现。

(特别是,看看 Tormod 的实现,你会发现它实际上与下面的 DistinctByImpl() 方法相同,所以这个答案应该被认为是他的扩展。)

如果使用 DistinctBy(),则解决方案变得如此简单:

var uniques = list.DistinctBy(item => item.LinkId);

在Jon Skeet 的DistinctBy()中可以找到一个很好的实现,该库也可以在 NuGet 上找到MoreLinq

例如,这是一个使用来自 MoreLinq 的 DistinctBy() 实现的副本的实现。不过不要使用此代码 - 使用 NuGet 下载原始注释代码。

using System;
using System.Linq;
using System.Collections.Generic;

namespace Demo
{
    public static class Program
    {
        public static void Main(string[] args)
        {
            List<Test> list = new List<Test>
            {
                new Test(1, 1),
                new Test(2, 1),
                new Test(3, 2),
                new Test(4, 2)
            };

            var uniques = list.DistinctBy(item => item.LinkId);

            foreach (var item in uniques)
            {
                Console.WriteLine(item);
            }
        }
    }

    public class Test
    {
        public Test(int linkSysId, int linkId)
        {
            LinkSysId = linkSysId;
            LinkId = linkId;
        }

        public override string ToString()
        {
            return string.Format("LinkSysId = {0}, LinkId = {1}", LinkSysId, LinkId);
        }

        public int LinkSysId;
        public int LinkId;
    }

    static class EnumerableExt
    {
        public static IEnumerable<TSource> DistinctBy<TSource, TKey>
            (this IEnumerable<TSource> source, Func<TSource, TKey> keySelector)
        {
            return source.DistinctBy(keySelector, null);
        }

        public static IEnumerable<TSource> DistinctBy<TSource, TKey>(this IEnumerable<TSource> source,
            Func<TSource, TKey> keySelector, IEqualityComparer<TKey> comparer)
        {
            if (source == null) throw new ArgumentNullException("source");
            if (keySelector == null) throw new ArgumentNullException("keySelector");
            return DistinctByImpl(source, keySelector, comparer);
        }

        private static IEnumerable<TSource> DistinctByImpl<TSource, TKey>(IEnumerable<TSource> source,
            Func<TSource, TKey> keySelector, IEqualityComparer<TKey> comparer)
        {
            var knownKeys = new HashSet<TKey>(comparer);
            return source.Where(element => knownKeys.Add(keySelector(element)));
        }
    }
}
于 2013-03-21T13:56:25.250 回答
1

“创造新”的方法:

DataTable keepTheseRows = table.AsEnumerable()
    .GroupBy(r => r.Field<int>("LinkId"))
    .Select(g => g.First())  // takes the first of each group arbitrarily
    .CopyToDataTable();
于 2013-03-21T13:27:00.663 回答