Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/gwt/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C#如何避免列表中的重复?_C#_List_Hashset - Fatal编程技术网

C#如何避免列表中的重复?

C#如何避免列表中的重复?,c#,list,hashset,C#,List,Hashset,我可以用什么方法避免列表中的重复项 一种方法是,当我要添加一个新项时,首先检查元素是否存在,但这会让我使用更多代码并迭代所有列表以检查它是否存在 另一种方法是使用hashset,如果我尝试添加一个新项,它本身检查该项是否存在,如果不存在,它将添加新项,如果存在,则不执行任何操作 但是我知道hashset效率较低,需要比列表更多的资源,所以我不知道使用hashset避免重复是否是hashset的一个好用途 还有其他选择吗 谢谢。您可以通过一行代码实现这一点:- List<long> l

我可以用什么方法避免列表中的重复项

一种方法是,当我要添加一个新项时,首先检查元素是否存在,但这会让我使用更多代码并迭代所有列表以检查它是否存在

另一种方法是使用hashset,如果我尝试添加一个新项,它本身检查该项是否存在,如果不存在,它将添加新项,如果存在,则不执行任何操作

但是我知道hashset效率较低,需要比列表更多的资源,所以我不知道使用hashset避免重复是否是hashset的一个好用途

还有其他选择吗


谢谢。

您可以通过一行代码实现这一点:-

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 };