如何从c#数组中删除重复项?

我一直在使用c#中的string[]数组,它从函数调用中返回。我可以强制转换为Generic集合,但我想知道是否有更好的方法,可能是使用临时数组。

从c#数组中删除重复项的最佳方法是什么?

394060 次浏览

如果您需要对它进行排序,那么您可以实现一个也删除重复项的排序。

那就一石二鸟了。

你可以使用一个LINQ查询来做到这一点:

int[] s = { 1, 2, 3, 3, 4};
int[] q = s.Distinct().ToArray();

将所有字符串添加到字典中,然后获取Keys属性。这将产生每个唯一的字符串,但不一定与原始输入的顺序相同。

如果你要求最终结果与原始输入的顺序相同,当你考虑每个字符串的第一次出现时,使用以下算法:

  1. 有一个列表(最终输出)和一个字典(检查重复)
  2. 对于输入中的每个字符串,检查它是否已经存在于字典中
  3. 如果不是,将它同时添加到字典和列表中

最后,列表包含每个唯一字符串的第一次出现。

在编写词典时,一定要考虑到文化等因素,以确保正确处理带有重音字母的重复项。

下面经过测试和工作的代码将从数组中删除重复项。你必须包括系统。集合名称空间。

string[] sArray = {"a", "b", "b", "c", "c", "d", "e", "f", "f"};
var sList = new ArrayList();


for (int i = 0; i < sArray.Length; i++) {
if (sList.Contains(sArray[i]) == false) {
sList.Add(sArray[i]);
}
}


var sNew = sList.ToArray();


for (int i = 0; i < sNew.Length; i++) {
Console.Write(sNew[i]);
}

如果你愿意,你可以把它打包成一个函数。

这可能取决于你有多想设计解决方案-如果数组永远不会那么大,你不关心排序列表,你可能想尝试类似于下面的东西:

    public string[] RemoveDuplicates(string[] myList) {
System.Collections.ArrayList newList = new System.Collections.ArrayList();


foreach (string str in myList)
if (!newList.Contains(str))
newList.Add(str);
return (string[])newList.ToArray(typeof(string));
}

注意:未测试!

string[] test(string[] myStringArray)
{
List<String> myStringList = new List<string>();
foreach (string s in myStringArray)
{
if (!myStringList.Contains(s))
{
myStringList.Add(s);
}
}
return myStringList.ToString();
}

也许能满足你的需要…

编辑啊! !不到一分钟就被抢了!

下面是HashSet< string>方法:

public static string[] RemoveDuplicates(string[] s)
{
HashSet<string> set = new HashSet<string>(s);
string[] result = new string[set.Count];
set.CopyTo(result);
return result;
}

不幸的是,这个解决方案也需要。net框架3.5或更高版本,因为HashSet直到该版本才被添加。你也可以使用array.Distinct (),这是LINQ的一个特性。

List<String> myStringList = new List<string>();
foreach (string s in myStringArray)
{
if (!myStringList.Contains(s))
{
myStringList.Add(s);
}
}

这是O (n ^ 2),对于一个将被塞进组合中的短列表来说,这无关紧要,但对于一个大型集合来说,这可能很快就会成为一个问题。

下面是一个使用O (1)空间的O (n * n)方法。

void removeDuplicates(char* strIn)
{
int numDups = 0, prevIndex = 0;
if(NULL != strIn && *strIn != '\0')
{
int len = strlen(strIn);
for(int i = 0; i < len; i++)
{
bool foundDup = false;
for(int j = 0; j < i; j++)
{
if(strIn[j] == strIn[i])
{
foundDup = true;
numDups++;
break;
}
}


if(foundDup == false)
{
strIn[prevIndex] = strIn[i];
prevIndex++;
}
}


strIn[len-numDups] = '\0';
}
}

上面的散列/ linq方法是你在现实生活中通常会使用的方法。然而,在面试中,他们通常想要设置一些约束,例如常量空间,这就排除了哈希,或者没有内部api -这就排除了使用LINQ

下面这段代码试图从ArrayList中删除重复项,尽管这不是最佳解决方案。在一次面试中,我被问到通过递归删除重复项,而不使用第二个/temp数组列表:

private void RemoveDuplicate()
{


ArrayList dataArray = new ArrayList(5);


dataArray.Add("1");
dataArray.Add("1");
dataArray.Add("6");
dataArray.Add("6");
dataArray.Add("6");
dataArray.Add("3");
dataArray.Add("6");
dataArray.Add("4");
dataArray.Add("5");
dataArray.Add("4");
dataArray.Add("1");


dataArray.Sort();


GetDistinctArrayList(dataArray, 0);
}


private void GetDistinctArrayList(ArrayList arr, int idx)


{


int count = 0;


if (idx >= arr.Count) return;


string val = arr[idx].ToString();
foreach (String s in arr)
{
if (s.Equals(arr[idx]))
{
count++;
}
}


if (count > 1)
{
arr.Remove(val);
GetDistinctArrayList(arr, idx);
}
else
{
idx += 1;
GetDistinctArrayList(arr, idx);
}
}
protected void Page_Load(object sender, EventArgs e)
{
string a = "a;b;c;d;e;v";
string[] b = a.Split(';');
string[] c = b.Distinct().ToArray();


if (b.Length != c.Length)
{
for (int i = 0; i < b.Length; i++)
{
try
{
if (b[i].ToString() != c[i].ToString())
{
Response.Write("Found duplicate " + b[i].ToString());
return;
}
}
catch (Exception ex)
{
Response.Write("Found duplicate " + b[i].ToString());
return;
}
}
}
else
{
Response.Write("No duplicate ");
}
}
可能是不存储重复元素的哈希集,并且默默地忽略添加请求 重复。< / p >
static void Main()
{
string textWithDuplicates = "aaabbcccggg";


Console.WriteLine(textWithDuplicates.Count());
var letters = new HashSet<char>(textWithDuplicates);
Console.WriteLine(letters.Count());


foreach (char c in letters) Console.Write(c);
Console.WriteLine("");


int[] array = new int[] { 12, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2 };


Console.WriteLine(array.Count());
var distinctArray = new HashSet<int>(array);
Console.WriteLine(distinctArray.Count());


foreach (int i in distinctArray) Console.Write(i + ",");
}

测试了以下&它的工作原理。最酷的是,它还做了一个文化敏感搜索

class RemoveDuplicatesInString
{
public static String RemoveDups(String origString)
{
String outString = null;
int readIndex = 0;
CompareInfo ci = CultureInfo.CurrentCulture.CompareInfo;




if(String.IsNullOrEmpty(origString))
{
return outString;
}


foreach (var ch in origString)
{
if (readIndex == 0)
{
outString = String.Concat(ch);
readIndex++;
continue;
}


if (ci.IndexOf(origString, ch.ToString().ToLower(), 0, readIndex) == -1)
{
//Unique char as this char wasn't found earlier.
outString = String.Concat(outString, ch);
}


readIndex++;


}




return outString;
}




static void Main(string[] args)
{
String inputString = "aAbcefc";
String outputString;


outputString = RemoveDups(inputString);


Console.WriteLine(outputString);
}

——AptSenSDET

——这是面试问题每次都问的问题。现在我完成了它的编码。

static void Main(string[] args)
{
int[] array = new int[] { 4, 8, 4, 1, 1, 4, 8 };
int numDups = 0, prevIndex = 0;


for (int i = 0; i < array.Length; i++)
{
bool foundDup = false;
for (int j = 0; j < i; j++)
{
if (array[i] == array[j])
{
foundDup = true;
numDups++; // Increment means Count for Duplicate found in array.
break;
}
}


if (foundDup == false)
{
array[prevIndex] = array[i];
prevIndex++;
}
}


// Just Duplicate records replce by zero.
for (int k = 1; k <= numDups; k++)
{
array[array.Length - k] = '\0';
}




Console.WriteLine("Console program for Remove duplicates from array.");
Console.Read();
}

这段代码从数组中100%删除重复值[因为我使用了一个[I]].....您可以将其转换为任何OO语言.....:)

for(int i=0;i<size;i++)
{
for(int j=i+1;j<size;j++)
{
if(a[i] == a[j])
{
for(int k=j;k<size;k++)
{
a[k]=a[k+1];
}
j--;
size--;
}
}


}

简单的解决方案:

using System.Linq;
...


public static int[] Distinct(int[] handles)
{
return handles.ToList().Distinct().ToArray();
}

你可以在使用数组列表时使用这段代码

ArrayList arrayList;
//Add some Members :)
arrayList.Add("ali");
arrayList.Add("hadi");
arrayList.Add("ali");


//Remove duplicates from array
for (int i = 0; i < arrayList.Count; i++)
{
for (int j = i + 1; j < arrayList.Count ; j++)
if (arrayList[i].ToString() == arrayList[j].ToString())
arrayList.Remove(arrayList[j]);
public static int RemoveDuplicates(ref int[] array)
{
int size = array.Length;


// if 0 or 1, return 0 or 1:
if (size  < 2) {
return size;
}


int current = 0;
for (int candidate = 1; candidate < size; ++candidate) {
if (array[current] != array[candidate]) {
array[++current] = array[candidate];
}
}


// index to count conversion:
return ++current;
}

下面是一个简单的java逻辑,你遍历数组的元素两次,如果你看到任何相同的元素,你赋0给它,加上你不触及你正在比较的元素的索引。

import java.util.*;
class removeDuplicate{
int [] y ;


public removeDuplicate(int[] array){
y=array;


for(int b=0;b<y.length;b++){
int temp = y[b];
for(int v=0;v<y.length;v++){
if( b!=v && temp==y[v]){
y[v]=0;
}
}
}
}
  private static string[] distinct(string[] inputArray)
{
bool alreadyExists;
string[] outputArray = new string[] {};


for (int i = 0; i < inputArray.Length; i++)
{
alreadyExists = false;
for (int j = 0; j < outputArray.Length; j++)
{
if (inputArray[i] == outputArray[j])
alreadyExists = true;
}
if (alreadyExists==false)
{
Array.Resize<string>(ref outputArray, outputArray.Length + 1);
outputArray[outputArray.Length-1] = inputArray[i];
}
}
return outputArray;
}

泛型扩展方法:

public static IEnumerable<TSource> Distinct<TSource>(this IEnumerable<TSource> source, IEqualityComparer<TSource> comparer)
{
if (source == null)
throw new ArgumentNullException(nameof(source));


HashSet<TSource> set = new HashSet<TSource>(comparer);
foreach (TSource item in source)
{
if (set.Add(item))
{
yield return item;
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;




namespace Rextester
{
public class Program
{
public static void Main(string[] args)
{
List<int> listofint1 = new List<int> { 4, 8, 4, 1, 1, 4, 8 };
List<int> updatedlist= removeduplicate(listofint1);
foreach(int num in updatedlist)
Console.WriteLine(num);
}




public static List<int> removeduplicate(List<int> listofint)
{
List<int> listofintwithoutduplicate= new List<int>();




foreach(var num in listofint)
{
if(!listofintwithoutduplicate.Any(p=>p==num))
{
listofintwithoutduplicate.Add(num);
}
}
return listofintwithoutduplicate;
}
}






}
strINvalues = "1,1,2,2,3,3,4,4";
strINvalues = string.Join(",", strINvalues .Split(',').Distinct().ToArray());
Debug.Writeline(strINvalues);

不确定这是巫术还是漂亮的代码

1 strINvalues .Split(',').Distinct().ToArray()

2字符串。加入(”、“XXX);

1拆分数组并使用Distinct [LINQ]删除重复项 2在没有重复的情况下将它连接回来。

抱歉,我从来没有读过StackOverFlow上的文本,只是代码。它比文本更有意义;)

最好的方法?很难说,HashSet方法看起来很快, 但是(取决于数据)使用排序算法(CountSort ?)

using System;
using System.Collections.Generic;
using System.Linq;
class Program
{
static void Main()
{
Random r = new Random(0); int[] a, b = new int[1000000];
for (int i = b.Length - 1; i >= 0; i--) b[i] = r.Next(b.Length);
a = new int[b.Length]; Array.Copy(b, a, b.Length);
a = dedup0(a); Console.WriteLine(a.Length);
a = new int[b.Length]; Array.Copy(b, a, b.Length);
var w = System.Diagnostics.Stopwatch.StartNew();
a = dedup0(a); Console.WriteLine(w.Elapsed); Console.Read();
}


static int[] dedup0(int[] a)  // 48 ms
{
return new HashSet<int>(a).ToArray();
}


static int[] dedup1(int[] a)  // 68 ms
{
Array.Sort(a); int i = 0, j = 1, k = a.Length; if (k < 2) return a;
while (j < k) if (a[i] == a[j]) j++; else a[++i] = a[j++];
Array.Resize(ref a, i + 1); return a;
}


static int[] dedup2(int[] a)  //  8 ms
{
var b = new byte[a.Length]; int c = 0;
for (int i = 0; i < a.Length; i++)
if (b[a[i]] == 0) { b[a[i]] = 1; c++; }
a = new int[c];
for (int j = 0, i = 0; i < b.Length; i++) if (b[i] > 0) a[j++] = i;
return a;
}
}

几乎没有分支。怎么做?调试模式,步进(F11)与一个小数组:{1,3,1,1,0}

    static int[] dedupf(int[] a)  //  4 ms
{
if (a.Length < 2) return a;
var b = new byte[a.Length]; int c = 0, bi, ai, i, j;
for (i = 0; i < a.Length; i++)
{ ai = a[i]; bi = 1 ^ b[ai]; b[ai] |= (byte)bi; c += bi; }
a = new int[c]; i = 0; while (b[i] == 0) i++; a[0] = i++;
for (j = 0; i < b.Length; i++) a[j += bi = b[i]] += bi * i; return a;
}
有两个嵌套循环的解决方案可能需要一些时间,

    static int[] dedup(int[] a)
{
int i, j, k = a.Length - 1;
for (i = 0; i < k; i++)
for (j = i + 1; j <= k; j++) if (a[i] == a[j]) a[j--] = a[k--];
Array.Resize(ref a, k + 1); return a;
}
int size = a.Length;
for (int i = 0; i < size; i++)
{
for (int j = i + 1; j < size; j++)
{
if (a[i] == a[j])
{
for (int k = j; k < size; k++)
{
if (k != size - 1)
{
int temp = a[k];
a[k] = a[k + 1];
a[k + 1] = temp;


}
}
j--;
size--;
}
}
}

删除重复和忽略区分大小写使用Distinct &StringComparer。InvariantCultureIgnoreCase

string[] array = new string[] { "A", "a", "b", "B", "a", "C", "c", "C", "A", "1" };
var r = array.Distinct(StringComparer.InvariantCultureIgnoreCase).ToList();
Console.WriteLine(r.Count); // return 4 items

在下面找到答案。

class Program
{
static void Main(string[] args)
{
var nums = new int[] { 1, 4, 3, 3, 3, 5, 5, 7, 7, 7, 7, 9, 9, 9 };
var result = removeDuplicates(nums);
foreach (var item in result)
{
Console.WriteLine(item);
}
}
static int[] removeDuplicates(int[] nums)
{
nums = nums.ToList().OrderBy(c => c).ToArray();
int j = 1;
int i = 0;
int stop = 0;
while (j < nums.Length)
{
if (nums[i] != nums[j])
{
nums[i + 1] = nums[j];
stop = i + 2;
i++;
}
j++;
}
nums = nums.Take(stop).ToArray();
return nums;
}
}
只是基于我刚刚解决的一个测试的一点贡献,可能有帮助,并开放给其他顶级贡献者的改进。 下面是我做的事情:

  1. 我使用OrderBy,它允许我使用LINQ从最小到最高对项目进行排序
  2. 然后将其转换回数组,然后将其重新分配回主数据源
  3. 然后我把数组右边的j初始化为1,把数组左边的i初始化为0,我还把i停止的地方初始化为0。
  4. 我使用了一个while循环,通过从一个位置到另一个位置从左到右递增数组,对于每个增量,停止位置是I + 2的当前值,我将在后面使用它来截断数组中的重复项。
  5. 然后从if语句中从左向右移动,在if语句外从右向右移动,直到遍历整个数组的值。
  6. 然后,我从第一个元素选取到停止位置,这成为最后一个I索引加2。这样我就可以从int数组中删除所有重复的项。然后重新分配。

所以我在做一个面试时,得到了同样的问题来分类和区分

static void Sort()
{
try
{
int[] number = new int[Convert.ToInt32(Console.ReadLine())];
for (int i = 0; i < number.Length; i++)
{
number[i] = Convert.ToInt32(Console.ReadLine());
}
Array.Sort(number);
int[] num = number.Distinct().ToArray();
for (int i = 0; i < num.Length; i++)
{
Console.WriteLine(num[i]);
}
}
catch (Exception ex)
{
Console.WriteLine(ex);
}
Console.Read();
}