如何将linq结果转换为HashSet或HashedSet

ss2ws0br  于 9个月前  发布在  其他
关注(0)|答案(9)|浏览(104)

我在一个ISet类上有一个属性。我试图将linq查询的结果获取到该属性中,但不知道如何操作。
基本上,寻找这最后一部分:

ISet<T> foo = new HashedSet<T>();
foo = (from x in bar.Items select x).SOMETHING;

字符串
也可以这样做:

HashSet<T> foo = new HashSet<T>();
foo = (from x in bar.Items select x).SOMETHING;

svdrlsy4

svdrlsy41#

编辑(2023):现在有一个ToHashSet扩展方法-参见下面的Douglas' answer

  • 原始答案 *:

我不认为有任何内置的东西可以做到这一点.

public static class Extensions
{
    public static HashSet<T> ToHashSet<T>(
        this IEnumerable<T> source,
        IEqualityComparer<T> comparer = null)
    {
        return new HashSet<T>(source, comparer);
    }
}

字符串
请注意,您确实需要一个扩展方法(或者至少是某种形式的泛型方法),因为您可能无法显式地表达T的类型:

var query = from i in Enumerable.Range(0, 10)
            select new { i, j = i + 1 };
var resultSet = query.ToHashSet();


你不能通过显式调用HashSet<T>构造函数来实现这一点,我们依赖于泛型方法的类型推断来完成这一任务。
现在你可以选择将其命名为ToSet并返回ISet<T>--但我坚持使用ToHashSet和具体类型。这与标准LINQ操作符(ToDictionaryToList)一致,并允许将来扩展(例如ToSortedSet)。你可能还想提供一个指定要使用的比较的重载。

gorkyyrv

gorkyyrv2#

只需将您的IE传入HashSet的构造函数。

HashSet<T> foo = new HashSet<T>(from x in bar.Items select x);

字符串

xytpbqjk

xytpbqjk3#

此功能已作为IEnumerable<TSource>上的扩展方法添加到.NET Framework 4.7.2和.NET Core 2.0。因此,它也可用于.NET 5和更高版本。

kx7yvsdv

kx7yvsdv4#

正如@Joel所说,你可以只传入你的可扩展对象。如果你想做一个扩展方法,你可以这样做:

public static HashSet<T> ToHashSet<T>(this IEnumerable<T> items)
{
    return new HashSet<T>(items);
}

字符串

ltqd579y

ltqd579y5#

在.NET框架和.NET核心中构建了一个扩展方法,用于将IEnumerable转换为HashSethttps://learn.microsoft.com/en-us/dotnet/api/?term=ToHashSet

public static System.Collections.Generic.HashSet<TSource> ToHashSet<TSource> (this System.Collections.Generic.IEnumerable<TSource> source);

字符串
看起来我还不能在.NET标准库中使用它(在写这篇文章的时候)。所以我使用这个扩展方法:

[Obsolete("In the .NET framework and in NET core this method is available, " +
              "however can't use it in .NET standard yet. When it's added, please remove this method")]
public static HashSet<T> ToHashSet<T>(this IEnumerable<T> source, IEqualityComparer<T> comparer = null) => new HashSet<T>(source, comparer);

s2j5cfk0

s2j5cfk06#

这很简单:)

var foo = new HashSet<T>(from x in bar.Items select x);

字符串
是的,T是OP指定的类型:)

q9rjltbz

q9rjltbz7#

如果您只需要对集合进行只读访问,并且源代码是方法的参数,那么我会选择

public static ISet<T> EnsureSet<T>(this IEnumerable<T> source)
{
    ISet<T> result = source as ISet<T>;
    if (result != null)
        return result;
    return new HashSet<T>(source);
}

字符串
原因是,用户可能已经用ISet调用了你的方法,所以你不需要创建副本。

erhoui1w

erhoui1w8#

Jon的回答是完美的。唯一的警告是,使用NHibernate的HashedSet,我需要将结果转换为集合。有没有最佳的方法来做到这一点?

ISet<string> bla = new HashedSet<string>((from b in strings select b).ToArray());

字符串

ISet<string> bla = new HashedSet<string>((from b in strings select b).ToList());


还是我错过了什么?
编辑:这是我最终做的:

public static HashSet<T> ToHashSet<T>(this IEnumerable<T> source)
{
    return new HashSet<T>(source);
}

public static HashedSet<T> ToHashedSet<T>(this IEnumerable<T> source)
{
    return new HashedSet<T>(source.ToHashSet());
}

vs3odd8k

vs3odd8k9#

与简单地将IELTS转换为HashSet不同,将另一个对象的属性转换为HashSet通常很方便。您可以将其写为:

var set = myObject.Select(o => o.Name).ToHashSet();

字符串
但是,我更喜欢使用选择器:

var set = myObject.ToHashSet(o => o.Name);


他们做同样的事情,第二个显然更短,但我发现这个成语更适合我的大脑(我认为它就像ToDictionary)。
下面是要使用的扩展方法,支持自定义比较器作为奖励。

public static HashSet<TKey> ToHashSet<TSource, TKey>(
    this IEnumerable<TSource> source,
    Func<TSource, TKey> selector,
    IEqualityComparer<TKey> comparer = null)
{
    return new HashSet<TKey>(source.Select(selector), comparer);
}

相关问题