我得到了一个简单的整体列表。
List<int> myInts = new List<int>();
myInts.Add(0);
myInts.Add(1);
myInts.Add(4);
myInts.Add(6);
myInts.Add(24);
我的目标是从列表中获取第一个未使用的(可用)值。
(集合中尚未出现的第一个正值)
在这种情况下,答案是2。
这是我目前的代码:
int GetFirstFreeInt()
{
for (int i = 0; i < int.MaxValue; ++i)
{
if(!myInts.Contains(i))
return i;
}
throw new InvalidOperationException("All integers are already used.");
}
有更好的方法吗?也许使用LINQ?你会怎么做?
当然,为了简单起见,我使用了int,但我的问题适用于任何类型。
答案 0 :(得分:18)
您基本上需要0..int.MaxValue
中未包含的序列myInts
中的第一个元素:
int? firstAvailable = Enumerable.Range(0, int.MaxValue)
.Except(myInts)
.FirstOrDefault();
编辑以回复评论:
此处有无性能损失,以迭代int.MaxValue
。 Linq将在内部创建的是一个哈希表myInts
,然后开始迭代Enumerable.Range()
创建的序列 - 一旦哈希表中未包含的第一个项被发现整数由Except()
产生{1}}方法并由FirstOrDefault()
返回 - 之后迭代停止。这意味着整体努力是O(n)用于创建哈希表,然后是最坏情况O(n)用于迭代序列,其中n是myInts
中的整数数。
有关Except()
的详情,请参阅Jon Skeet的EduLinq系列:Reimplementing LINQ to Objects: Part 17 - Except
答案 1 :(得分:2)
好吧,如果列表从最小到最大排序并且包含从0到正无穷大的值,则可以简单地访问第i个元素。 if (myInts[i] != i) return i;
本质上是相同的,但不需要在每个Contains
检查中遍历列表(Contains方法遍历列表,将算法转换为O(n平方)而不是O(n))。