C#如何避免列表中的重复?
我可以用什么方法避免列表中的重复项 一种方法是,当我要添加一个新项时,首先检查元素是否存在,但这会让我使用更多代码并迭代所有列表以检查它是否存在 另一种方法是使用hashset,如果我尝试添加一个新项,它本身检查该项是否存在,如果不存在,它将添加新项,如果存在,则不执行任何操作 但是我知道hashset效率较低,需要比列表更多的资源,所以我不知道使用hashset避免重复是否是hashset的一个好用途 还有其他选择吗C#如何避免列表中的重复?,c#,list,hashset,C#,List,Hashset,我可以用什么方法避免列表中的重复项 一种方法是,当我要添加一个新项时,首先检查元素是否存在,但这会让我使用更多代码并迭代所有列表以检查它是否存在 另一种方法是使用hashset,如果我尝试添加一个新项,它本身检查该项是否存在,如果不存在,它将添加新项,如果存在,则不执行任何操作 但是我知道hashset效率较低,需要比列表更多的资源,所以我不知道使用hashset避免重复是否是hashset的一个好用途 还有其他选择吗 谢谢。您可以通过一行代码实现这一点:- List<long> l
谢谢。您可以通过一行代码实现这一点:-
List<long> longs = new List<long> { 1, 2, 3, 4, 3, 2, 5 };
List<long> unique = longs.Distinct().ToList();
List longs=新列表{1,2,3,4,3,2,5};
List unique=longs.Distinct().ToList();
unique
将只包含1,2,3,4,5列表是一个可能包含重复项的数据结构。重复元素通过其索引消除歧义
一种方法是,当我要添加一个新项时,首先检查元素是否存在,但这会让我使用更多代码并迭代所有列表以检查它是否存在
这是可能的,但它容易出错且速度慢。每次添加元素时,都需要遍历整个列表。您还可能忘记检查代码中的某个地方
另一种方法是使用hashset,如果我尝试添加一个新项,它本身检查该项是否存在,如果不存在,它将添加新项,如果存在,则不执行任何操作
这是首选的方式。最好使用标准库来强制执行所需的约束
但是我知道hashset效率较低,需要比列表更多的资源,所以我不知道使用hashset避免重复是否是hashset的一个好用途
效率取决于你想做什么;看
还有其他选择吗
您可以使用
List
实现自己的ISet
。这将使插入速度大大降低(您需要迭代整个集合),但您将获得O(1)
随机访问 哈希集是检查项是否存在的最佳方法,因为它是O(1)
因此,您可以在列表和哈希集中插入项目
在插入新项之前,请检查它是否存在于哈希集中。在哈希集中,无法避免重复项。不可能-没有对项目的验证 如果你不在意物品的顺序,那就用吧 若你们想保持项目的顺序(实际上有点模糊——项目应该出现在第一次添加的索引中还是最后一次添加的索引中)。但是如果您想确保所有项目都是唯一的,那么您应该编写自己的列表类。也就是说,实现IList接口的东西:
public class ListWithoutDuplicates<T> : IList<T>
一些基于索引的操作:
public int IndexOf(T item)
{
var hash = item.GetHashCode();
if (!hashes.Contains(hash))
return -1;
return items.IndexOf(item);
}
public void Insert(int index, T item)
{
var itemAtIndex = items[index];
if (comparer.Compare(item, itemAtIndex) == 0)
return;
var hash = item.GetHashCode();
if (!hashes.Contains(hash))
{
hashes.Remove(itemAtIndex.GetHashCode());
items[index] = item;
hashes.Add(hash);
return;
}
throw new ArgumentException("Cannot add duplicate item");
}
public void RemoveAt(int index)
{
var item = items[index];
hashes.Remove(item.GetHashCode());
items.RemoveAt(index);
}
剩下的是:
public T this[int index]
{
get { return items[index]; }
set { Insert(index, value); }
}
public int Count => items.Count;
public bool Contains(T item) => hashes.Contains(item.GetHashCode());
public IEnumerator<T> GetEnumerator() => items.GetEnumerator();
IEnumerator IEnumerable.GetEnumerator() => items.GetEnumerator();
public T此[int索引]
{
获取{返回项[索引];}
集合{插入(索引,值);}
}
public int Count=>items.Count;
public bool Contains(T item)=>hashes.Contains(item.GetHashCode());
public IEnumerator GetEnumerator()=>items.GetEnumerator();
IEnumerator IEnumerable.GetEnumerator()=>items.GetEnumerator();
就这样。现在您有了列表实现,它将只添加一次项(第一次)。例如
var list=没有重复项的新列表{1,2,1,3,5,2,5,3,4};
将创建包含项目1、2、3、5、4的列表。注意:如果内存消耗比性能更重要,则使用项代替哈希。包含操作,该操作为O(n)
顺便说一句,我们刚才所做的实际上是一个IList使用哈希集
,它不会降低您的性能。请检查这一点,还有其他选择,但根据您的项目大小,它们可能不适合。HashSet
更好,因为它可以删除重复项并保证O(1)
Add
和包含
。但是您也可以将元素添加到列表中,然后使用LINQ使用Distinct().ToList()
。这取决于您的用例。“但我知道哈希集效率较低”,这是错误的。它不是一个列表,所以它不提供通过索引的访问。除此之外,它非常有效,但我知道hashset效率较低,需要比列表更多的资源。你能提供更多的细节(例子)吗?如果你想实现<代码> IcLoops<代码>,它不允许重复,同时仍然保留一个排序,考虑使用<代码> SooTeSET> <代码>,而不是<代码>列表< /C>。所以每次添加一个项目时,你都想这样做吗?非常inefficient@AnandSystematix:如果您事先准备好了所有项目,这可能就足够了,但如果列表将按需填写,并且这对性能至关重要,则这是不可行的。OP希望在添加过程中避免重复,他不想删除重复。@M.kazemAkhgary:好的,什么时间段,每5分钟一次?然而,你有一段时间处于不一致状态。那一点也不好。如果你运气好,客户没有注意到这个错误,我不认为这是对“如何避免列表中重复”问题的回答。避免集合中的重复项并使用重复项从集合中选择唯一的项-这是不同的事情。OP给出的不使用HashSet
的唯一原因是性能,这比仅使用HashSet
效率要低得多。正如其他人提到的,它也不会“避免”重复。这意味着要有一个持续唯一的集合,比如HashSet
。
public int IndexOf(T item)
{
var hash = item.GetHashCode();
if (!hashes.Contains(hash))
return -1;
return items.IndexOf(item);
}
public void Insert(int index, T item)
{
var itemAtIndex = items[index];
if (comparer.Compare(item, itemAtIndex) == 0)
return;
var hash = item.GetHashCode();
if (!hashes.Contains(hash))
{
hashes.Remove(itemAtIndex.GetHashCode());
items[index] = item;
hashes.Add(hash);
return;
}
throw new ArgumentException("Cannot add duplicate item");
}
public void RemoveAt(int index)
{
var item = items[index];
hashes.Remove(item.GetHashCode());
items.RemoveAt(index);
}
public T this[int index]
{
get { return items[index]; }
set { Insert(index, value); }
}
public int Count => items.Count;
public bool Contains(T item) => hashes.Contains(item.GetHashCode());
public IEnumerator<T> GetEnumerator() => items.GetEnumerator();
IEnumerator IEnumerable.GetEnumerator() => items.GetEnumerator();
var list = new ListWithoutDuplicates<int> { 1, 2, 1, 3, 5, 2, 5, 3, 4 };