Question : 现在有一个字符数组 :
let arr = [\"盆\",\"盆\",\"学\",\"I\",\"T\",\"越\",\"学\",\"越\",\"牛\",\"B\",\"!\"];
你有几种方法去除数组中重复的内容呢?
方法一 ES6 Set去重let arr = [\"盆\", \"盆\", \"学\", \"I\", \"T\", \"越\", \"学\", \"越\", \"牛\", \"B\", \"!\"];function uniqueArray(arr) { return Array.from(new Set(arr))}console.log(uniqueArray(arr)); //[ '盆', '学', 'I', 'T', '越', '牛', 'B', '!' ]方法二 for循环+ splice去重
let arr = [\"盆\", \"盆\", \"学\", \"I\", \"T\", \"越\", \"学\", \"越\", \"牛\", \"B\", \"!\"];function uniqueArray(arr) { for (let i = 0; i < arr.length; i++) { for (let j = i + 1; j < arr.length; j++) { if (arr[j] === arr[i]) { arr.splice(j, 1); j--; } } } return arr}console.log(uniqueArray(arr)); // [ '盆', '学', 'I', 'T', '越', '牛', 'B', '!' ]
想想:如果我写成如下的形式,会有什么问题?
function uniqueArray(arr) { let len = arr.length; for (let i = 0; i < len; i++) { for (let j = i + 1; j < len; j++) { if (arr[j] === arr[i]) { arr.splice(j, 1); j--; } } } return arr}方法三 indexOf 去重
let arr = [\"盆\", \"盆\", \"学\", \"I\", \"T\", \"越\", \"学\", \"越\", \"牛\", \"B\", \"!\"];function uniqueArray(arr) { if (!Array.isArray(arr)) { console.log('type error!'); return; } var array = []; for (var i = 0; i < arr.length; i++) { if (arraydexOf(arr[i]) === -1) { array.push(arr[i]) } } return array;}console.log(uniqueArray(arr)); // [ '盆', '学', 'I', 'T', '越', '牛', 'B', '!' ]
方法四 利用sort()函数去重
let arr = [\"盆\", \"盆\", \"学\", \"I\", \"T\", \"越\", \"学\", \"越\", \"牛\", \"B\", \"!\"];// 利用sort()排序方法,然后根据排序后的结果进行遍历及相邻元素比对function uniqueArray(arr) { if (!Array.isArray(arr)) { console.log('type error!') return; } arr = arrrt() var arrry= [arr[0]]; for (var i = 1; i < arr.length; i++) { if (arr[i] !== arr[i-1]) { arrry.push(arr[i]); } } return arrry;}console.log(uniqueArray(arr)); // [ '盆', '学', 'I', 'T', '越', '牛', 'B', '!' ]方法五 利用includes
let arr = [\"盆\", \"盆\", \"学\", \"I\", \"T\", \"越\", \"学\", \"越\", \"牛\", \"B\", \"!\"];function uniqueArray(arr) { var array =[]; //includes 检测数组是否有某个值 for(var i = 0; i < arr.length; i++) { if( !arraycludes( arr[i]) ) { array.push(arr[i]); } } return array}console.log(uniqueArray(arr)); // [ '盆', '学', 'I', 'T', '越', '牛', 'B', '!' ]方法六 利用 filter + hasOwnProperty
let arr = [\"盆\", \"盆\", \"学\", \"I\", \"T\", \"越\", \"学\", \"越\", \"牛\", \"B\", \"!\"];function uniqueArray(arr) { var obj = {}; return arr.filter(function(item){ return obj.hasOwnProperty(typeof item + item) ? false : (obj[typeof item + item] = true) })}console.log(uniqueArray(arr)); // [ '盆', '学', 'I', 'T', '越', '牛', 'B', '!' ]方法七 利用 filter + indexOf
let arr = [\"盆\", \"盆\", \"学\", \"I\", \"T\", \"越\", \"学\", \"越\", \"牛\", \"B\", \"!\"];function uniqueArray(arr) { return arr.filter(function(item, index, arr) { //当前元素,在原始数组中的第一个索引==当前索引值,否则返回当前元素 return arrdexOf(item,0) === index; });}console.log(uniqueArray(arr)); // [ '盆', '学', 'I', 'T', '越', '牛', 'B', '!' ]方法八 递归法
let arr = [\"盆\", \"盆\", \"学\", \"盆\", \"I\", \"T\", \"越\", \"学\", \"越\", \"牛\", \"B\", \"!\"];
function uniqueArray(arr) {
let array = arr;
let len = array.length;
arrayrt();//首先排序,相同元素在一起,方便后续递归去重
function loop(index) {
if (index >= 1) {
if (array[index] === array[index - 1]) {
array.splice(index, 1);
}
loop(index - 1); //递归loop
}
}
loop(len - 1);
return array;
}
console.log(uniqueArray(arr)); // [ '!', 'B', 'I', 'T', '学', '牛', '盆', '越' ]
方法九 Map数据结构去重let arr = [\"盆\", \"盆\", \"学\", \"盆\", \"I\", \"T\", \"越\", \"学\", \"越\", \"牛\", \"B\", \"!\"];function uniqueArray(arr) { let map = new Map(); let array = [] // 数组用于返回结果 for (let i = 0; i < arr.length; i++) { if (map.has(arr[i])) { // 如果有该key值 map.set(arr[i], true); } else { map.set(arr[i], false); // 如果没有该key值 array.push(arr[i]); } } return array;}console.log(uniqueArray(arr)); // [ '盆', '学', 'I', 'T', '越', '牛', 'B', '!' ]方法十 reduce+includes
let arr = [\"盆\", \"盆\", \"学\", \"盆\", \"I\", \"T\", \"越\", \"学\", \"越\", \"牛\", \"B\", \"!\"];function uniqueArray(arr) { return arruce((prev,cur) => prevcludes(cur) ? prev : [...prev,cur]);}console.log(uniqueArray(arr)); // [ '盆', '学', 'I', 'T', '越', '牛', 'B', '!' ]方法十一 懒人法
[...new Set(arr)] // 对于不想多写代码的人来说,这么一句就够了!
这么多种方法,你都学会了吗?
你还有什么更好的方法,欢迎留言讨论吧!
/*1、利用ES6 Set去重(ES6中最常用)*/
function unique1(arr) {
return Array.from(new Set(arr)) //[1, \"true\", true, false, undefined, null, NaN, \"NaN\", 0, \"a\", {}, {}]
}
/*2.利用for嵌套for,然后splice去重(ES5中最常用)*/
function unique2(arr) {
for(var i = 0; i < arr.length; i++) {
for(var j = i + 1; j < arr.length; j++) {
if(arr[i] == arr[j]) {
arr.splice(j,1);
j--;
}
}
}
return arr; //[1, \"true\", false, undefined, NaN, NaN, \"NaN\", \"a\", {…}, {…}] //NaN和{}没有去重,两个null直接消失了
}
/*3.利用indexOf去重*/
function unique3(arr) {
if(!Array.isArray(arr)) {
console.log('type error!')
return
}
var array = [];
for(var i = 0; i < arr.length; i++) {
if(arraydexOf(arr[i]) === -1) {
array.push(arr[i])
}
}
return array; // [1, \"true\", true, false, undefined, null, NaN, NaN, \"NaN\", 0, \"a\", {…}, {…}] //NaN、{}没有去重
}
/*4 利用sort()*/
function unique4(arr) {
if(!Array.isArray(arr)) {
console.log('type error!')
return
}
arr = arrrt()
var array = [arr[0]];
for(var i = 1; i < arr.length; i++) {
if(arr[i] !== arr[i-1]) {
array.push(arr[i]);
}
}
return array; // [0, 1, \"NaN\", NaN, NaN, {…}, {…}, \"a\", false, null, true, \"true\", undefined] //NaN、{}没有去重
}
/*五、利用对象的属性不能相同的特点进行去重*/
function unique5(arr) {
if(!Array.isArray(arr)) {
console.log('type error!')
return
}
var array = [];
var obj = {};
for(var i = 0; i < arr.length; i++) {
if(!obj[arr[i]]) {
array.push(arr[i])
obj[arr[i]] = 1;
}else {
obj[arr[i]] ++
}
}
return array; //[1, \"true\", false, undefined, null, NaN, 0, \"a\", {…}] //两个true直接去掉了,NaN和{}去重
}
/*六、利用includes*/
function unique6(arr) {
if(!Array.isArray(arr)) {
console.log('type error!')
return
}
var array = [];
for(var i = 0; i < arr.length; i++) {
if(!arraycludes(arr[i])) {
array.push(arr[i])
}
}
return array //[1, \"true\", true, false, undefined, null, NaN, \"NaN\", 0, \"a\", {…}, {…}] //{}没有去重
}
/*七、利用hasOwnProperty !!!所有的去重了*/
function unique7(arr) {
var obj = {};
return arr.filter(function(item,index,arr) {
return obj.hasOwnProperty(typeof item + item) ? false : (obj[typeof item + item] = true); //[1, \"true\", true, false, undefined, null, NaN, \"NaN\", 0, \"a\", {…}] 所有的都去重了
})
}
/*八、利用filter*/
function unique8(arr) {
return arr.filter(function(item, index, arr) {
return arrdexOf(item, 0) === index; //[1, \"true\", true, false, undefined, null, \"NaN\", 0, \"a\", {…}, {…}]
});
}
/*九、利用递归去重*/
function unique9(arr) {
var array = arr;
var len = array.length;
arrayrt(function(a,b) {
return a - b;
})
function loop(index) {
if(index >= 1) {
if(array[index] === array[index - 1]) {
array.splice(index,1)
}
loop(index - 1); //递归loop,然后数组去重
}
}
loop(len - 1);
return array; //[1, \"a\", \"true\", true, false, 1, {…}, null, NaN, NaN, \"NaN\", 0, \"a\", {…}, undefined]
}
/*十、利用Map数据结构去重*/
function unique10(arr) {
let map = new Map();
let array = new Array(); //数组用于返回结果
for(let i = 0; i < arr.length; i++) {
if(map.has(arr[i])) {
map.set(arr[i],true);
}else {
map.set(arr[i],false); //如果没有该key值;
array.push(arr[i]);
}
}
return array; //(12) [1, \"true\", true, false, undefined, null, NaN, \"NaN\", 0, \"a\", {…}, {…}]
}
/*十一、利用reduce+includes*/
function unique11(arr) {
return arruce((prev,cur) => prevcludes(cur) ? prev : [...prev,cur],[]); //(12) [1, \"true\", true, false, undefined, null, NaN, \"NaN\", 0, \"a\", {…}, {…}]
}
/*十二、[...new Set(arr)]*/
function unique12(arr) {
return [...new Set(arr)] //(12) [1, \"true\", true, false, undefined, null, NaN, \"NaN\", 0, \"a\", {…}, {…}]
}
/*十三. lodash _.uniq([2, 1, 2]);// => [2, 1] 需要引入lodash*/
导读:在数据分析当中,Python用到最多的第三方库就是Numpy。本文内容是「大数据DT」内容合伙人王皓阅读学习《Python 3智能数据分析快速入门》过后的思考和补充,结合这本书一起学习,效果更佳。
作者:王皓
来源:华章科技
01 ndarray创建与索引在学习Numpy之前我们需要了解一个概念:数组维数。
在计算机科学中,数组数据结构(array data structure),简称数组(Array),是由相同类型的元素的集合所组成的数据结构,分配一块连续的内存来存储。按数组维数分类可分为:一维数组、二维数组、多维数组(N维数组)。
Numpy是最著名的 Python库之一,常用于高性能计算。Numpy提供了两种基本对象:ndarray和ufunc。
NumPy作为一个开源的Python科学计算基础库,包含:一个强大的N维数组对象ndarray ;广播功能函数 ;整合C/C++/Fortran代码的工具 ;线性代数、傅里叶变换、随机数生成等功能。NumPy是SciPy、Pandas等数据处理或科学计算库的基础。
当然这里就有一个问题出现了,Python已有列表类型,为什么需要一个数组对象(类型)?
因为:
数组对象可以去掉元素间运算所需的循环,使一维向量更像单个数据设置专门的数组对象,经过优化,可以提升这类应用的运算速度,在科学计算中,一个维度所有数据的类型往往相同数组对象采用相同的数据类型,有助于节省运算和存储空间但是Python内置的array模块既不支持多维数组功能,又没有配套对应的计算函数,所以基于Numpy的ndarray在很大程度上改善了Python内置array模块的不足,将重点介绍ndarray的创建与索引。
1. 创建ndarray对象
1)ndarray数据类型
在《Python 3智能数据分析快速入门》该节内容中,作者罗列了15种数据类型,其中实数数据类型13种。这些实数数据类型之间可以互相转换。
这时有人会问,为什么要支持这么多种数据类型?是因为对比Python语法来说仅支持整数、浮点数和复数3种类型,但是当科学计算涉及数据较多,对存储和性能都有较高要求,所以对数据类型进行精细定义,有助于NumPy合理使用存储空间并优化性能和程序员对程序规模有合理评估。
对于15种数据类型在这里笔者将不赘述,书上有详细的解释以及案例示范。
2)ndarray创建
在《Python 3智能数据分析快速入门》该节内容中,作者介绍了两种创建ndarray的方法:
使用array函数创建数ndarray使用arange函数创建数ndarray这里笔者再补充四种方法并整理出来:
从Python中的列表、元组等类型创建ndarray数组使用NumPy中函数创建ndarray数组,如:arange, ones, zeros等从字节流(raw bytes)中创建ndarray数组从文件中读取特定格式,创建ndarray数组对于方法②再补充5个常用函数:
np.full(shape,val):根据shape生成一个数组,每个元素值都是valnp.ones_like(a):根据数组a的形状生成一个全1数组np.zeros_like(a):根据数组a的形状生成一个全0数组np.full_like(a,val):根据数组a的形状生成一个数组,每个元素值都是valnpncatenate():将两个或多个数组合并成一个新的数组3)随机数
Numpy提供了强大的生成随机数的功能,使用随机数也能创建ndarray。基本语法格式:numpy.random.×××() 。在《Python 3智能数据分析快速入门》该节内容中,作者罗列了13个函数及其说明,笔者再补充2个函数:
choice(a[,size,replace,p]):从一维数组a中以概率p抽取元素,形成size形状新数组 replace表示是否可以重用元素,默认为Falsepoisson(lam,size):产生具有泊松分布的数组,lam随机事件发生率,size形状2. ndarray的索引和切片
索引与切片是ndarray使用频率最高的操作。相较于list,ndarray索引与切片在功能上更加丰富,在形式上更多样。ndarray的高效率在很大程度上需归功于其索引的易用性。
1)一维ndarray的索引
一维ndarray的索引方法很简单,与list的索引方法一致,相关案例在书上有展示,这里不再赘述。
2)多维ndarray的索引
多维的每一个维度都有一个索引,各个维度的索引之间用逗号隔开,例如:arr[ [维度1(行)] , [维度2(列)] ]。
代码清单如下:
import numpy as npprint(np.arange(10))
输出:[0 1 2 3 4 5 6 7 8 9]
arrnp.array([[1,2,3,4,5],[4,5,6,7,8],[7,8,9,10,11]])print('\n',arr)
输出:
[[ 1 2 3 4 5]
[ 4 5 6 7 8]
[ 7 8 9 10 11]]
#访问第0行中第3列和第4列元素print('切片结果:',arr[0,3:5])
输出:
切片结果:[4 5]
#访问第1行和第二行中第2列、第3列和第4列的元素print('切片结果:\n',arr[1:,2:])
输出:
切片结果:
[6 7 8]
[9 10 11]
#访问第2列的元素print('切片结果:',arr[:2])
输出:
切片结果:[3 6 9]
ndarray在索引与切片的时候除了使用整形的数据外,还可以使用布尔型,代码清单如下:
# 索引第1、3行中第2列的元素。Define true 1, define false 0mask=np.array([1, 0, 1], dtype=np.bool)print(arr[mask, 1])
输出:
[2 8]
3)花式索引
花式索引是一个Numpy术语,是在基础索引方式之上衍生出的功能更强大的索引方式。它能够利用整数ndarray进行索引。
在这节的学习中,发现一个有趣的问题:在使用np.empty函数时,本想用arr = np.empty((4,7))创建一个空的多维数组,但是返回的结果是这样:
语法格式数值等都没有什么错误的情况下,初步怀疑是函数本身的原因,于是用help()函数查看它的详细介绍,竟然查到了:
数据类型是可选且默认值是numpy.float64。(好家伙,书上可没告诉我)所以只需在后面选择int就行。
arr = np.empty((4,7),int)print(arr)
输出:
另一个问题是关于ix函数生成区域索引器的问题,代码如下:
arr = np.array([np.arange(i*4, i*4+4) for i in np.arange(6)])print('创建的二维ndarray arr为:\n', arr)
输出:
#利用np.ix函数将两个一维的整数ndarray转化为方形区域的索引器print('使用ix成片索引arr结果为:\n', arr[np.ix_([5, 1, 4, 2], [3, 0, 1, 2])])
输出:
out[15]为什么会返回这样一个结果?是因为ix函数结果的排序是基于[5,1,4,2],[3,0,1,2]两个数组产生的笛卡尔积,即(5,3),(5,0),(5,1),(5,2);(1,3),(1,0),(1,1),(1,2);(4,3),(4,0),(4,1),(4,2);(2,3),(2,0),(2,1),(2,2)。然后按照索引(5,3),(5,0),(5,1),(5,2)得到第0行元素:23 20 21 22,之后的以此类推。
02 ndarray的基础操作ndarray的基础操作包括设置ndarray形状、展平ndarray、组合ndarray、分割ndarray、ndarray的排序与搜索,以及ndarray的字符串操作等。
设置ndarray形状书中已经介绍了12种基本函数和它们的代码演示:
通过reshape方法改变ndarray形状通过resize方法改变ndarray形状通过修改shape属性改变ndarray维度使用ravel方法展平ndarray使用flatten方法展平ndarray使用hstack函数实现ndarray横向组合使用vstack函数实现ndarray纵向组合使用concatenate函数组合ndarray使用dstack函数组合ndarray使用hsplit函数实现ndarray横向分割使用vsplit函数实现ndarray纵向分割使用split函数分割ndarray使用dsplit函数实现ndarray深度分割在这里做几点补充和说明:
.swapaxes(ax1,ax2):将数组n个维度中两个维度进行调换.astype(new_type):一定会创建新的数组(原始数据的一个拷贝),即使两个类型一致.tolist( ):将数组或者矩阵转换成列表但请注意深度分割函数dsplit的使用条件:
import numpy as nparr=np.arange(12)
arr.shape = (4, 3)print('\n', arr)
输出:
[[ 0 1 2]
[ 3 4 5]
[ 6 7 8]
[ 9 10 11]]
print('形状改变后, ndarray arr的维度为:',arr.ndim)
输出:
形状改变后,ndarray arr的维度为:2
'''dsplit分割的ndarray必须是三维ndarray,且分割的数目必须为shape属性中下标为2的值的公约数。比如这里的分割数就是36,下标为2的值是4,符合要求'''arr = np.arange(36).reshape(3,3,4)print('创建的三维ndarrary arr为:\n',arr)
创建的三维 ndarrary arr为:
[[[ 0 1 2 3]
[ 4 5 6 7]
[ 8 9 10 11]]
[[ 12 13 14 15]
[ 16 17 18 19]
[ 20 21 22 23]]
[[ 24 25 26 27]
[ 28 29 30 31]
[ 32 33 34 35]]]
1. 排序与搜索
书中已经介绍了6种基本函数和它们的代码演示:
使用sort函数进行排序使用argsort函数进行排序使用argmax和argmin函数进行搜索使用where函数无x与y使用where函数有x与y使用extract函数进行搜索在这里做几点补充和说明:
其中注意argsort函数使用的方法类似于sort,只是返回的值不同,返回的是ndarray arr的下标。
2. 字符串操作
Numpy的char模块提供的字符串操作函数可以运用向量化运算来处理整个ndarray,而完成同样的任务,Python的列表则通常借助循环语句遍历列表,并对逐个元素进行相应的处理。
Numpy的char模块提供的常用字符串操作函数具有字符串的连接、切片、删除、替换、字母大小写转换和编码调用等功能,可谓是十分方便,书上有非常详细的介绍,建议大家结合《Python 3智能数据分析快速入门》这本书美味食用。
03 ufuncufunc,全称通用函数(universal function),是一种能够对ndarray中所有元素进行操作的函数,而不是对ndarray对象操作。
ufunc的广播机制广播(Broadingcasting)是指不同形状的ndarray之间执行算术运算的方式。若两个ndarray的shape不一致,Numpy则会实行广播机制。为了更好地使用广播机制,需要遵循4个原则。原则及案例在书上第159页有详细演示,此处不再赘述。
常用ufunc常用的ufunc运算有算数运算、三角函数、集合运算、比较运算、逻辑运算和统计计算等。书上提供了若干种常用函数,对ndarray中所有元素的运算来说,在提供了极其方便与快捷的同时,又囊括一切强大的功能。相关函数及案例在书上第161页有详细演示,此处不再赘述。
04 matrix与线性代数Numpy的matrix是继承自Numpy的二维ndarray对象,不仅拥有二维ndarray的属性、方法与函数,还拥有诸多特有的属性与方法。同时,Numpy中的matrix与线性代数中的矩阵概念几乎完全相同,同样含有转置矩阵、共轭矩阵、逆矩阵等概念。
只要是大学期间学过《线性代数》这门课程的同学,对于《Python 3智能数据分析快速入门》的学习完全没有问题,相关专业术语及技术实现细节在本节中都有强调。详情请从第169页开始学习。
05 Numpy文件读写读写文件是利用Numpy进行数据处理的基础,Numpy中主要有二进制的文件读写和文件列表形式的数据读写两种形式。其中二进制文件读取使用书上第175页中提到的load函数;二进制文件存储使用save和savez函数。
但是在实际的数据分析任务中,更多使用文本格式的数据,如txt或csv,因此经常使用loadtxt函数执行对文本格式的数据的读取任务和savetxt函数执行对文本格式的数据的存储任务。
但是它们只能有效存取一维和二维数据,这里我再对多维数据的存取的方法进行补充:
a.tofile(frame, sep='', format='%s')
frame:文件、字符串sep:数据分割字符串,如果是空串,写入文件为二进制format:写入数据的格式np.fromfile(frame, dtype=float, count=‐1, sep='')
frame:文件、字符串dtype:读取的数据类型count:读入元素个数,‐1表示读入整个文件sep:数据分割字符串,如果是空串,写入文件为二进制需要注意的是,该方法需要读取时知道存入文件时数组的维度和元素类型,a.tofile()和np.fromfile()需要配合使用,可以通过元数据文件来存储额外信息。
06 小结本章重点介绍了Numpy数值计算重要的基础内容,主要包含如下6部分内容。
ndarray基础知识,包括ndarray的属性与创建方法。ndarray使用的切片和索引方法,改变ndarray形状的方式,ndarray的排序、搜索与字符串操作等。ufunc的广播功能及常用的ufunc,包括算术运算函数、三角函数、集合运算函数、比较运算函数、逻辑运算函数和统计计算函数等。矩阵的创建、属性及基本运算。Numpy中二进制的文件读写和文件列表形式的数据读写。参考文献:
1. 《Python 3智能数据分析快速入门》 李明江、张良均、周东平、张尚佳 著,机械工业出版社出版。
2大学MOOC,《Python数据分析与展示》作者:嵩天 。
3.百度百科:数组维数
4.CSDN:《花式索引与np.ix_函数》TzeSing 著
5.CSDN:《关于np.empty()函数的用法》爱数据的橙子 著
关于作者:王皓,一名就读于北京石油化工学院大数据管理与应用专业的同学,热爱并致力于学习Python语言及相关应用领域。大数据DT内容合伙人。
延伸阅读《Python3智能数据分析快速入门》
推荐语:本书假设你有一定的数据分析基础,但是没有Python和AI基础,为了帮助你快速掌握智能数据分析需要的技术和方法,书中有针对性地讲解了Python和AI中必须要掌握的知识点,内容由浅入深,循序渐进。从环境配置、基本语法、基础函数到第三方库的安装与使用,对各个操作步骤、函数、工具、代码示例等的讲解非常详尽,确保所有满足条件的读者都能快速入门。
Question : 现在有一个字符数组 :
let arr = [\"盆\",\"盆\",\"学\",\"I\",\"T\",\"越\",\"学\",\"越\",\"牛\",\"B\",\"!\"];
你有几种方法去除数组中重复的内容呢?
方法一 ES6 Set去重let arr = [\"盆\", \"盆\", \"学\", \"I\", \"T\", \"越\", \"学\", \"越\", \"牛\", \"B\", \"!\"];function uniqueArray(arr) { return Array.from(new Set(arr))}console.log(uniqueArray(arr)); //[ '盆', '学', 'I', 'T', '越', '牛', 'B', '!' ]方法二 for循环+ splice去重
let arr = [\"盆\", \"盆\", \"学\", \"I\", \"T\", \"越\", \"学\", \"越\", \"牛\", \"B\", \"!\"];function uniqueArray(arr) { for (let i = 0; i < arr.length; i++) { for (let j = i + 1; j < arr.length; j++) { if (arr[j] === arr[i]) { arr.splice(j, 1); j--; } } } return arr}console.log(uniqueArray(arr)); // [ '盆', '学', 'I', 'T', '越', '牛', 'B', '!' ]
想想:如果我写成如下的形式,会有什么问题?
function uniqueArray(arr) { let len = arr.length; for (let i = 0; i < len; i++) { for (let j = i + 1; j < len; j++) { if (arr[j] === arr[i]) { arr.splice(j, 1); j--; } } } return arr}方法三 indexOf 去重
let arr = [\"盆\", \"盆\", \"学\", \"I\", \"T\", \"越\", \"学\", \"越\", \"牛\", \"B\", \"!\"];function uniqueArray(arr) { if (!Array.isArray(arr)) { console.log('type error!'); return; } var array = []; for (var i = 0; i < arr.length; i++) { if (arraydexOf(arr[i]) === -1) { array.push(arr[i]) } } return array;}console.log(uniqueArray(arr)); // [ '盆', '学', 'I', 'T', '越', '牛', 'B', '!' ]
方法四 利用sort()函数去重
let arr = [\"盆\", \"盆\", \"学\", \"I\", \"T\", \"越\", \"学\", \"越\", \"牛\", \"B\", \"!\"];// 利用sort()排序方法,然后根据排序后的结果进行遍历及相邻元素比对function uniqueArray(arr) { if (!Array.isArray(arr)) { console.log('type error!') return; } arr = arrrt() var arrry= [arr[0]]; for (var i = 1; i < arr.length; i++) { if (arr[i] !== arr[i-1]) { arrry.push(arr[i]); } } return arrry;}console.log(uniqueArray(arr)); // [ '盆', '学', 'I', 'T', '越', '牛', 'B', '!' ]方法五 利用includes
let arr = [\"盆\", \"盆\", \"学\", \"I\", \"T\", \"越\", \"学\", \"越\", \"牛\", \"B\", \"!\"];function uniqueArray(arr) { var array =[]; //includes 检测数组是否有某个值 for(var i = 0; i < arr.length; i++) { if( !arraycludes( arr[i]) ) { array.push(arr[i]); } } return array}console.log(uniqueArray(arr)); // [ '盆', '学', 'I', 'T', '越', '牛', 'B', '!' ]方法六 利用 filter + hasOwnProperty
let arr = [\"盆\", \"盆\", \"学\", \"I\", \"T\", \"越\", \"学\", \"越\", \"牛\", \"B\", \"!\"];function uniqueArray(arr) { var obj = {}; return arr.filter(function(item){ return obj.hasOwnProperty(typeof item + item) ? false : (obj[typeof item + item] = true) })}console.log(uniqueArray(arr)); // [ '盆', '学', 'I', 'T', '越', '牛', 'B', '!' ]方法七 利用 filter + indexOf
let arr = [\"盆\", \"盆\", \"学\", \"I\", \"T\", \"越\", \"学\", \"越\", \"牛\", \"B\", \"!\"];function uniqueArray(arr) { return arr.filter(function(item, index, arr) { //当前元素,在原始数组中的第一个索引==当前索引值,否则返回当前元素 return arrdexOf(item,0) === index; });}console.log(uniqueArray(arr)); // [ '盆', '学', 'I', 'T', '越', '牛', 'B', '!' ]方法八 递归法
let arr = [\"盆\", \"盆\", \"学\", \"盆\", \"I\", \"T\", \"越\", \"学\", \"越\", \"牛\", \"B\", \"!\"];
function uniqueArray(arr) {
let array = arr;
let len = array.length;
arrayrt();//首先排序,相同元素在一起,方便后续递归去重
function loop(index) {
if (index >= 1) {
if (array[index] === array[index - 1]) {
array.splice(index, 1);
}
loop(index - 1); //递归loop
}
}
loop(len - 1);
return array;
}
console.log(uniqueArray(arr)); // [ '!', 'B', 'I', 'T', '学', '牛', '盆', '越' ]
方法九 Map数据结构去重let arr = [\"盆\", \"盆\", \"学\", \"盆\", \"I\", \"T\", \"越\", \"学\", \"越\", \"牛\", \"B\", \"!\"];function uniqueArray(arr) { let map = new Map(); let array = [] // 数组用于返回结果 for (let i = 0; i < arr.length; i++) { if (map.has(arr[i])) { // 如果有该key值 map.set(arr[i], true); } else { map.set(arr[i], false); // 如果没有该key值 array.push(arr[i]); } } return array;}console.log(uniqueArray(arr)); // [ '盆', '学', 'I', 'T', '越', '牛', 'B', '!' ]方法十 reduce+includes
let arr = [\"盆\", \"盆\", \"学\", \"盆\", \"I\", \"T\", \"越\", \"学\", \"越\", \"牛\", \"B\", \"!\"];function uniqueArray(arr) { return arruce((prev,cur) => prevcludes(cur) ? prev : [...prev,cur]);}console.log(uniqueArray(arr)); // [ '盆', '学', 'I', 'T', '越', '牛', 'B', '!' ]方法十一 懒人法
[...new Set(arr)] // 对于不想多写代码的人来说,这么一句就够了!
这么多种方法,你都学会了吗?
你还有什么更好的方法,欢迎留言讨论吧!