我需要删除列表中的所有重复项,但前提是列表a中的项目也与列表b中的相同。这是我当前的代码,但是要处理10万个项目,实际上需要几天的时间,有没有一种快速的方法?
任何帮助表示赞赏。
List<int> ind = new List<int>();
List<int> used = new List<int>();
for (int i = 0; i < a.Count; i++)
{
for (int j = 0; j < a.Count; j++)
{
if (i != j&&!used.Contains(i))
{
if (a[j] == a[i] && b[i] == b[j])
{
ind.Add(j);
used.Add(j);
}
}
}
}
List<string> s2 = new List<string>();
List<string> a2 = new List<string>();
for (int i = 0; i < a.Count; i++)
{
if (!ind.Contains(i))
{
s2.Add(a[i]);
a2.Add(b[i]);
}
}
答案 0 :(得分:2)
许多此类问题的关键是正确的数据结构。为避免重复,您需要使用Set,因为它们会自动删除重复。
这是Java中的代码,我希望它与C#类似:
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Random;
import java.util.Set;
class Duplicates
{
static List<Integer> list1 = new ArrayList<>();
static List<Integer> list2 = new ArrayList<>();
static final int SIZE = 100_000;
static final int MAX_VALUE = 1000_000;
public static void main(String[] args)
{
// populate the lists with random values for testing
Random r = new Random();
for(int i=0; i<SIZE; i++)
{
list1.add(r.nextInt(MAX_VALUE));
list2.add(r.nextInt(MAX_VALUE));
}
Set<Integer> set1 = new HashSet<>(list1);
Set<Integer> set2 = new HashSet<>(list2);
// items that are in both lists
Set<Integer> intersection = new HashSet<>(set1);
intersection.retainAll(set2);
Set<Integer> notSeenYet = new HashSet<>(intersection);
List<Integer> list1Unique = new ArrayList<Integer>();
for(int n: list1)
{
if(intersection.contains(n)) // we may have to skip this one
{
if(notSeenYet.contains(n)) // no, don't skip, it's the first occurrence
{
notSeenYet.remove(n);
}
else
{
continue;
}
}
list1Unique.add(n);
}
System.out.println("list 1 contains "+list1Unique.size()+" values after removing all duplicates that are also in list 2");
}
}
100k值只需不到一秒钟。
输出
列表1删除所有重复项后包含99591个值 也在清单2中
答案 1 :(得分:2)
这是要考虑的一般算法。我们可以从两个列表开始按升序排序。使用良好的排序算法(例如合并排序),这将花费O(NlgN)
时间,其中N
是列表的长度。支付完罚款后,我们只需在每个列表中维护两个指针。一般而言,一般算法将涉及遍历两个列表,如果有问题的值与a
列表中的指针匹配,则在第一个b
列表中搜索重复项。如果存在匹配项,则将从a
列表中删除重复项,否则我们将继续走直到到达a
列表的末尾。此过程仅为O(N)
,从而使最大的罚款成为O(NlgN)
的初始排序。
答案 2 :(得分:2)
创建一个HashSet
。
首先,遍历列表b
并将所有元素添加到HashSet中。
然后,遍历列表a
的每个元素。当您访问某个元素时,请询问HashSet它是否已包含该元素。如果不是,则这是一个新元素,因此只需保留它即可。如果是这样,它就是重复项,您可以将其从a
中删除。
HashSet可以在O(1)中执行Do you have this element?
问题,因此对于整个列表,您有O(n)。
有关更多信息,请检查documentation。
答案 3 :(得分:1)
要“删除重复项”,我的意思是“从n个相同的项目中,保留第一个并删除其余的n-1个”。如果是这样,那么这就是算法:
将列表b
转换为B
。还介绍集合A_dup
。遍历列表a
和每个项目:
A_dup
中找到了项目,则将其从a
中删除,B
中找到了项目,则将其添加到A_dup
。检查集合(A_dup
和B
中是否存在)是O(1)操作,也要在集合中添加新项目。因此,您剩下要遍历列表a
,这总共给了我们O(n)。
答案 4 :(得分:0)
我认为您想做的是找到不同的对,对吧?
如果是这样,则可以使用Distinct
和 var result = a.Zip(b, (x,y) => (x, y)).Distinct();
以及C#元组(或使用匿名类型)在一行中完成该操作。
usedRange
答案 5 :(得分:0)
import java.util.*;
import java.util.stream.Collectors;
public class Test {
public static void main(String args[]) {
List<String> dupliKhaneList = new ArrayList<>();
dupliKhaneList.add("Vaquar");
dupliKhaneList.add("Khan");
dupliKhaneList.add("Vaquar");
dupliKhaneList.add("Vaquar");
dupliKhaneList.add("Khan");
dupliKhaneList.add("Vaquar");
dupliKhaneList.add("Zidan");
// Solution 1 if want to remove in list
List<String> uniqueList = dupliKhaneList.stream().distinct().collect(Collectors.toList());
System.out.println("DupliKhane => " + dupliKhaneList);
System.out.println("Unique 1 => " + uniqueList);
// Solution 2 if want to remove using 2 list
List<String> list1 = new ArrayList<>();
list1.add("Vaquar");
list1.add("Khan");
list1.add("Vaquar");
list1.add("Vaquar");
list1.add("Khan");
list1.add("Vaquar");
list1.add("Zidan");
List<String> list2 = new ArrayList<>();
list2.add("Zidan");
System.out.println("list1 => " + list1);
System.out.println("list2 => " + list2);
list1.removeAll(list2);
System.out.println("removeAll duplicate => " + list1);
}
}
结果:
DupliKhane => [Vaquar, Khan, Vaquar, Vaquar, Khan, Vaquar, Zidan]
Unique 1 => [Vaquar, Khan, Zidan]
list1 => [Vaquar, Khan, Vaquar, Vaquar, Khan, Vaquar, Zidan]
list2 => [Zidan]
removeAll duplicate => [Vaquar, Khan, Vaquar, Vaquar, Khan, Vaquar]