将自定义选择器委托传递给 LINQ 的 GroupBy

本文关键字:LINQ GroupBy 自定义 选择器 | 更新日期: 2023-09-27 17:56:56

所以我有这个扩展名,它返回IEnumerable中重复项目(键)及其相应索引(值)的KeyValuePair

    public static IEnumerable<KeyValuePair<TSource, int[]>> GetDuplicates<TSource>(this IEnumerable<TSource> e)
    {
        return e.Select((value, index) => new { Index = index, Value = value })
                .GroupBy(x => x.Value)
                .Select(xg => new KeyValuePair<TSource, int[]>(xg.Key, xg.Select(x => x.Index).ToArray()))
                .Where(kv => kv.Value.Length > 1);
    }

我正在尝试做一件非常基本的事情 - 我想注入一个自定义选择器,以便我可以传递到GroupBy - 我尝试了这个:

    public static IEnumerable<KeyValuePair<TSource, int[]>> GetDuplicates<TSource, TKey>(this IEnumerable<TSource> e, Func<TSource, TKey> selector)
    {
        return e.Select((value, index) => new { Index = index, Value = value })
                .GroupBy(x => selector(x.Value))
                .Select(xg => new KeyValuePair<TSource, int[]>(xg.Key, xg.Select(x => x.Index).ToArray()))
                .Where(kv => kv.Value.Length > 1);
    }

但是我在KeyValuePair的新版本中得到了无效的参数错误.

似乎我对应该传递的所有通用参数感到困惑 - 我不确定如何连接它们:s

我认为这里的问题是选择器应该返回第一个Select投影的匿名类型 - 而不是 TKey - 但是我如何注入匿名类型泛型参数?

有什么想法吗?

谢谢。

编辑:

找到了一个解决方法 - 不是很好,但它有效并显示了我想要的。

    private static List<TSource> GetDups<TSource, TKey>(List<TSource> source, Func<TSource, TKey> selector)
    {
        var dupGosIndices = source
            .Select(selector)
            .GetDuplicates().Select(x => x.Value);
        var dupGos = new List<TSource>();
        foreach (IEnumerable<int> indicesList in dupGosIndices) {
            dupGos.Add(source[indicesList.ElementAt(0)]);
        }
        return dupGos;
    }

将自定义选择器委托传递给 LINQ 的 GroupBy

试试这个?IGrouping<Key, IEnumerable<TSource>>上的分组都将具有相同的 TSource 值,因此请继续获取第一个值。

            return e.Select((value, index) => new { Index = index, Value = value })
                .GroupBy(x => selector(x.Value))
                .Select(xg => new KeyValuePair<TSource, int[]>(xg.Select(x => x.Value).First(), xg.Select(x => x.Index).ToArray()))
                .Where(kv => kv.Value.Length > 1);