C# 从哈希集中获取X个最早的项?

C# 从哈希集中获取X个最早的项?,c#,.net,C#,.net,我有一个HashSet,它保存一个“Item”类实例的集合,在这个类Item中我有一个DateTime“AddedAt”,我试图从类中的AddedAt得到X个最早的项,但我不知道下一步该怎么做,有人能帮我吗 这就是我所能得到的 public List<Item> GetOldestItems(int count) { List<Item> items = new List<Item>(); foreach (Item item in _ite

我有一个HashSet,它保存一个“Item”类实例的集合,在这个类Item中我有一个DateTime“AddedAt”,我试图从类中的AddedAt得到X个最早的项,但我不知道下一步该怎么做,有人能帮我吗

这就是我所能得到的

public List<Item> GetOldestItems(int count)
{
    List<Item> items = new List<Item>();

    foreach (Item item in _itemsHashSet)
    {

    }

    return items;
}
OrderBy()。然后可以调用
Take(count)
从重新排序的枚举中获取第一个
n

public IEnumerable<Item> GetOldestItems(int count)
{
    return _itemsHashSet.OrderBy(i => i.AddedAt).Take(count);
}

这与@RacilHilan同样正确的答案在思维上的区别在于,我们经常在不创建集合的情况下链接多个LINQ调用:
OrderBy()
上面没有返回集合;例如,它返回
IOrderedEnumerable
Take(n)
返回
IEnumerable
。因此,根据LINQ的精神,假设调用方可以对我们返回的枚举执行进一步的LINQ操作。此外,我们实际上可能希望推迟执行。也许您希望保留结果,并每五分钟重新评估一次。如果尚未冻结列表中的当前结果,则my方法返回的枚举每次枚举时都将重新查询
\u itemsHashSet
,因此您将始终获得12个最早的项,但它们可能是12个不同的最早项。很酷的东西

var x = new ObservableCollection<DateTime>(
    GetOldestItems(12).Select(x => x.AddedAt).Reverse().Take(5));
var x=新的可观测集合(
GetOldestItems(12).Select(x=>x.AddedAt.Reverse().Take(5));
然而,就你的目的而言,在这一过程中创建一个额外的列表不太可能是一场职业生涯的灾难

OrderBy()
按选择器lambda返回的任何属性值的“最低优先”顺序返回枚举(
AddedAt
,在本例中)。然后可以调用
Take(count)
从重新排序的枚举中获取第一个
n

public IEnumerable<Item> GetOldestItems(int count)
{
    return _itemsHashSet.OrderBy(i => i.AddedAt).Take(count);
}

这与@RacilHilan同样正确的答案在思维上的区别在于,我们经常在不创建集合的情况下链接多个LINQ调用:
OrderBy()
上面没有返回集合;例如,它返回
IOrderedEnumerable
Take(n)
返回
IEnumerable
。因此,根据LINQ的精神,假设调用方可以对我们返回的枚举执行进一步的LINQ操作。此外,我们实际上可能希望推迟执行。也许您希望保留结果,并每五分钟重新评估一次。如果尚未冻结列表中的当前结果,则my方法返回的枚举每次枚举时都将重新查询
\u itemsHashSet
,因此您将始终获得12个最早的项,但它们可能是12个不同的最早项。很酷的东西

var x = new ObservableCollection<DateTime>(
    GetOldestItems(12).Select(x => x.AddedAt).Reverse().Take(5));
var x=新的可观测集合(
GetOldestItems(12).Select(x=>x.AddedAt.Reverse().Take(5));

然而,就你的目的而言,在这一过程中创建一个额外的列表不太可能是一场职业生涯的灾难

您必须先对列表进行排序,然后按索引选择第一个“计数”项。或者,您可以使用LINQ为您执行以下操作:

public List<Item> GetOldestItems(int count)
{
    return _itemsHashSet.OrderBy(i => i.AddedAt).Take(count).ToList();
}
公共列表GetOldestItems(整数计数)
{
return _itemsHashSet.OrderBy(i=>i.AddedAt).Take(count).ToList();
}

您必须先对列表进行排序,然后按索引选择第一个“计数”项。或者,您可以使用LINQ为您执行以下操作:

public List<Item> GetOldestItems(int count)
{
    return _itemsHashSet.OrderBy(i => i.AddedAt).Take(count).ToList();
}
公共列表GetOldestItems(整数计数)
{
return _itemsHashSet.OrderBy(i=>i.AddedAt).Take(count).ToList();
}

对于这种类型的查找,哈希集不是最好的集合类型,当使用哈希集时,您需要在AddedAt属性中将集合按IEnumerable降序排序(A
O(n log n)
操作),然后取排序后的可枚举的前x个值(请参阅该实现的其他答案)

如果与向散列集中添加新元素相比,要执行此操作,可以使用一个按日期排序的比较器。这确实会减慢从
O(1)
O(logn)
的哈希集查找和插入速度,但会加快从
O(1)
O(1)
的顶部项目的查找速度,因为在获取前x个项目之前无需进行排序

private sealed class AddedAtComparer : Comparer<Item>
{
    public override int Compare(Item x, Item y)
    {
        if (ReferenceEquals(x, y)) return 0;
        if (ReferenceEquals(null, y)) return 1;
        if (ReferenceEquals(null, x)) return -1;
        return x.AddedAt.CompareTo(y.AddedAt);
    }
}

private SortedSet<Item> _itemsHashSet = new SortedSet<Item>(new AddedAtComparer());
public List<Item> GetOldestItems(int count)
{
    return _itemsHashSet.Take(count).ToList();
}

对于这种类型的查找,哈希集不是最好的集合类型,当使用哈希集时,需要在AddedAt属性中将集合作为IEnumerable降序排序(A
O(n log n)
操作),然后获取排序后的可枚举数的前x个值(有关该实现,请参阅其他答案)

如果与向散列集中添加新元素相比,要执行此操作,可以使用一个按日期排序的比较器。这确实会减慢从
O(1)
O(logn)
的哈希集查找和插入速度,但会加快从
O(1)
O(1)
的顶部项目的查找速度,因为在获取前x个项目之前无需进行排序

private sealed class AddedAtComparer : Comparer<Item>
{
    public override int Compare(Item x, Item y)
    {
        if (ReferenceEquals(x, y)) return 0;
        if (ReferenceEquals(null, y)) return 1;
        if (ReferenceEquals(null, x)) return -1;
        return x.AddedAt.CompareTo(y.AddedAt);
    }
}

private SortedSet<Item> _itemsHashSet = new SortedSet<Item>(new AddedAtComparer());
public List<Item> GetOldestItems(int count)
{
    return _itemsHashSet.Take(count).ToList();
}

O(n+k log k),其中k是如果
Take
是order by–aware,则取的量。@Jonhana它不知道,表明它是一个简单的foreach循环,遍历IEnumerable而没有智能。NetFX版本不是,CoreFX版本是.O(n+k log k)式中,k是如果
Take
是order by–aware所取的量。@Jonhana它不知道,表明它是一个简单的foreach循环,在IEnumerable上没有智能。NetFX版本不是,CoreFX版本是。是在将项添加到哈希集中时添加的吗?如果是这样,那么当一个项目添加到两个集合时会发生什么?是否在该项目添加到散列集合时添加了?如果是这样,那么当一个项目添加到两个集合时会发生什么?