js中数组去重的方法

在JavaScript里,数组去重这事儿挺常见的,我来给你盘点几种高效又实用的方法。

首先是用Set()。
ES6 给咱带来了Set这个集合类型,它自带去重功能,挺方便。
你看这个例子: javascript const arr = ['a', 'b', 'c', 'a', 'd']; const uniqueArr = [...new Set(arr)]; // uniqueArr 就是 ['a', 'b', 'c', 'd']
Set的优点是简洁高效,时间复杂度接近O(n)。
不过,它没法直接处理对象类型的去重,因为对象的引用不同。

接下来是filter()和indexOf的组合。
这个方法兼容性好,ES5 以上的版本都能用。
原理是通过indexOf检查元素首次出现的索引是否等于当前索引。
代码像这样: javascript const arr = ['a', 'b', 'c', 'a', 'd']; const uniqueArr = arr.filter((item, index, self) => self.indexOf(item) === index);
不过,这个方法的缺点是时间复杂度较高,达到O(n²),所以不太适合处理大型数组。

第三个方法是forEach()和splice()。
这个方法会直接修改原数组,原理是遍历数组,发现重复项就删掉。
代码如下: javascript const arr = ['a', 'b', 'c', 'a', 'd']; arr.forEach((item, index, self) => { if (self.indexOf(item) !== index) { arr.splice(index, 1 ); } });
这个方法的缺点是它会改变原数组,可能会引发一些意外行为,比如跳过某些元素。
而且时间复杂度也是O(n²),性能不太理想。

第四种方法是reduce()。
这个方法通过累加器逐步构建一个没有重复项的数组。
代码像这样: javascript const arr = ['a', 'b', 'c', 'a', 'd']; const uniqueArr = arr.reduce((acc, item) => { if (!acc.includes(item)) { acc.push(item); } return acc; }, []);
reduce的优点是逻辑清晰,适合链式操作。
但它的缺点是includes在大型数组中效率不高,时间复杂度也是O(n²)。

那么,哪种方法更好呢?简单来说:
小型数组:随便用哪种方法都行,我比较推荐Set()或者filter(),代码简洁。

大型数组:最好用Set(),性能最好。

需要保留原数组:别用forEach+splice(),它会改掉原数组。

对象数组去重:得结合Map或者自定义键,比如用JSON.stringify。

最后,给你举个例子,怎么用Set去重对象数组: javascript const objArr = [{id: 1 }, {id: 2 }, {id: 1 }]; const uniqueObjArr = [...new Map(objArr.map(item => [item.id, item])).values()]; // uniqueObjArr 就是 [{id: 1 }, {id: 2 }]
总之,根据你的具体情况选择合适的方法,平衡一下可读性和性能就行。

JS数组去重有哪些方法

Hey, 今天来聊聊JavaScript数组去重的那点事儿。
去重,顾名思义,就是从数组中移除重复的元素,听起来简单,但具体操作起来,根据不同的场景,我们得选择不同的方法。

首先,对于基本数据类型的数组,比如数字或字符串,一个常用的方法是利用Set对象。
Set只存储唯一的值,所以用它去重特别快。
举个例子,如果你有一个数字数组[1 ,2 ,2 ,3 ,4 ,4 ,5 ],用Set去重后就会变成[1 ,2 ,3 ,4 ,5 ]。
这个方法的好处是代码简洁,性能也挺好,不过它只能处理基本数据类型,不能用于对象数组。

再来说说filter结合indexOf或includes的方法。
这个方法比较老牌,它通过遍历数组,只保留第一次出现的元素。
比如,如果你有一个数组[1 ,2 ,2 ,3 ,4 ,4 ,5 ],用filter和indexOf去重后,结果也是[1 ,2 ,3 ,4 ,5 ]。
这个方法思路清晰,但缺点是性能不是特别高,尤其是对于大数组来说。

对于复杂对象数组,我们可以用reduce结合Map或普通对象的方法来去重。
Map和普通对象都可以利用键的唯一性来去重,但Map更灵活,可以处理各种类型的唯一标识。
不过,Map的代码稍微复杂一些,需要你熟悉它的用法。

最后,咱们得聊聊性能和选择建议。
对于小规模数组,优先考虑可读性和代码简洁度,Set是个不错的选择。
中等规模数组,如果数组是基本数据类型,Set仍然是最佳选择;如果是对象数组,Map或普通对象都可以,看具体需求。
至于大规模数组,Set在基本数据类型上是唯一的选择,对于对象数组,Map或普通对象也行,但得确保唯一键的生成逻辑要高效。

PHP如何自定义数组去重方法

在PHP里头,自定义数组去重主要有两种思路,一种是基于值的去重,另一种是基于键值对的去重。
具体用哪种方法,得看你的需求和数组的大小来决定。

首先说说基于值的去重,这种方法不管是索引数组还是关联数组都适用。
它的核心原理是利用数组的值作为新数组的键,然后通过array_flip()函数来交换键值,最后取键来实现去重。
因为键是唯一的,所以新数组自然就实现了去重。
不过,这种方法会重置原数组的键,索引数组会变成数字索引,关联数组只会保留值。

举个例子,假设有一个索引数组$arr=[1 ,2 ,2 ,3 ,4 ,4 ,5 ],用uniqueByValue函数去重后,输出的新数组会是Array([0]=>1 [1 ]=>2 [2 ]=>3 [3 ]=>4 [4 ]=>5 )。
对于关联数组,比如$assocArr=[&3 9 ;a&3 9 ;=>1 ,&3 9 ;b&3 9 ;=>2 ,&3 9 ;c&3 9 ;=>2 ,&3 9 ;d&3 9 ;=>3 ],去重后键会被重置,输出的新数组会是Array([0]=>1 [1 ]=>2 [2 ]=>3 )。

这种方法的适用场景主要是当你只需要保留唯一的值,而不关心原来的键时,比如统计不重复的ID列表。
而且,因为它依赖于内置函数array_flip(),所以效率比较高。

接下来是基于键值对的去重,这种方法只适用于关联数组。
它的核心原理是通过一个辅助数组来存储序列化后的键值对,然后判断是否重复。
如果没重复,就把原来的键值对存入结果数组,同时保留原来的键。

比如,对于关联数组$assocArr=[&3 9 ;a&3 9 ;=>1 ,&3 9 ;b&3 9 ;=>2 ,&3 9 ;c&3 9 ;=>2 ,&3 9 ;a&3 9 ;=>3 ],用uniqueByKeyValuePair函数去重后,输出的新数组会是Array([a]=>3 [b]=>2 [c]=>2 ),这样就保留了最后一个重复键的值。

这种方法的适用场景主要是当你需要保留关联数组原来的键,或者对去重逻辑有比较精细的需求时,比如在处理配置文件去重时。
不过,因为涉及到序列化操作,所以效率相对较低,只适合小数组或者有特殊需求的情况。

总的来说,如果你想要快速去重并且不关心键,就选基于值的去重方法;如果你需要保留键或者有精细的去重需求,就选基于键值对的去重方法。
当然,还可以结合array_reduce()或者生成器函数来进一步优化性能。
对于多维数组,可能需要递归处理或者使用json_encode()来替代序列化。
理解了PHP数组的特点以及去重策略的核心差异,你就能灵活选择最适合的方案,写出既高效又健壮的代码了。

PHP数组循环、排序与去重:仅用循环和条件语句实现

在PHP里,如果你只想用循环和条件语句来搞定数组排序和去重,那冒泡排序和线性遍历去重是个不错的选择。
下面给你具体说说怎么实现,还有代码例子。

1 . 数组排序:冒泡排序 冒泡排序就是通过一遍遍比较相邻元素,把顺序搞错的给换过来,直到整个数组升序排列。
它的核心思路是这样的:外层循环控制排序的轮次,内层循环用来比较和交换相邻元素。
每轮排序结束后,最大的元素就像气泡一样“冒”到数组最后面去了,所以下一轮排序时,内层循环的范围就可以小一点。

代码实现是这样的:
php $input_array = [3 ,5 ,7 ,7 ,8 ,3 ,1 ,9 ,9 ,9 ,0,2 ,4 ,8 ,0,1 2 ,5 ,8 ,2 ]; $n = count($input_array);
// 冒泡排序 for ($i = 0; $i < $n
1 ; $i++) { for ($j = 0; $j < $n
1
$i; $j++) { if ($input_array[$j] > $input_array[$j + 1 ]) { // 交换元素 $temp = $input_array[$j]; $input_array[$j] = $input_array[$j + 1 ]; $input_array[$j + 1 ] = $temp; } } }
echo "排序后数组: " . implode(',', $input_array) . "\n";
排序后的数组会是这样的:0,0,1 ,2 ,2 ,3 ,3 ,4 ,5 ,5 ,7 ,7 ,8 ,8 ,8 ,9 ,9 ,9 ,1 2
2 . 数组去重:线性遍历 排序好了之后,重复的元素就都挨在一起了。
这时候,你只需要比较当前元素和前一个元素,如果它们不一样,那就保留当前元素。
第一个元素肯定保留,因为它前面没有东西。

代码实现:
php $n = count($input_array); echo "非重复元素: "; if ($n > 0) { echo $input_array[0]; // 输出第一个元素 for ($i = 1 ; $i < $n; $i++) { if ($input_array[$i] != $input_array[$i
1 ]) { echo "," . $input_array[$i]; } } } echo "\n";
去重后的结果会是:0,1 ,2 ,3 ,4 ,5 ,7 ,8 ,9 ,1 2
3 . 完整代码示例 把排序和去重结合起来,完整的代码长这样:
php $input_array = [3 ,5 ,7 ,7 ,8 ,3 ,1 ,9 ,9 ,9 ,0,2 ,4 ,8 ,0,1 2 ,5 ,8 ,2 ]; $n = count($input_array);
echo "原始数组: " . implode(',', $input_array) . "\n";
// 步骤1 :冒泡排序 for ($i = 0; $i < $n
1 ; $i++) { for ($j = 0; $j < $n
1
$i; $j++) { if ($input_array[$j] > $input_array[$j + 1 ]) { $temp = $input_array[$j]; $input_array[$j] = $input_array[$j + 1 ]; $input_array[$j + 1 ] = $temp; } } }
echo "排序后数组: " . implode(',', $input_array) . "\n";
// 步骤2 :去重 echo "非重复元素: "; if ($n > 0) { echo $input_array[0]; for ($i = 1 ; $i < $n; $i++) { if ($input_array[$i] != $input_array[$i
1 ]) { echo "," . $input_array[$i]; } } } echo "\n";
4 . 性能与注意事项 冒泡排序的时间复杂度是O(n²),不管是最好还是最坏情况都是这样。
去重的时间复杂度是O(n),所以整个流程的时间复杂度主要还是由排序决定的,也就是O(n²)。
空间复杂度是O(1 ),因为除了输入数组,我们只用了几个临时变量。

这种方法的适用场景主要是处理小规模数据,或者是在学习算法原理的时候用用。
实际开发中,为了提高性能,最好还是用PHP的内置函数,比如sort()和array_unique()。

5 . 内置函数对比 如果你可以用内置函数,代码可以简化很多:
php sort($input_array); $unique_array = array_unique($input_array); echo "非重复元素: " . implode(',', $unique_array) . "\n";
内置函数的优势在于,sort()的时间复杂度是O(nlogn),而array_unique()内部有优化,效率更高。

总的来说,虽然用冒泡排序和线性遍历去重的方法性能不是特别高,但确实能帮助你理解基础算法的逻辑,适合面试或者学习的时候用。
实际开发中,还是推荐使用PHP的内置函数来提高效率。