javascript数组减去另一数组

title

做聊天项目的时候遇要实现这样的一个功能: 邀请新的好友入群;点击邀请好友会弹出一个好友列表,显示你除了在群里面的好友外剩下的所有好友;
我的思路是取到你所有的好友,然后所有好友中过滤掉已经是群成员的好友

const users = [
    {
        _id: 1,
        name: '好友1'
    },
    {
        _id: 2,
        name: '好友1'
    },
    {
        _id: 3,
        name: '好友1'
    },
];
const groupMembers = [
    {
        _id: 1,
        name: '好友1'
    },
    {
        _id: 2,
        name: '好友1'
    },
]

现在一步一步来看数组的操作

一,两个数组里的每一项分别为元素时

const arr1 = ['', '100', '120', '125', '125', '130', '130'];

const arr2 = ['', '120', '125', '125', '130'];

请问如何求得两个数组之差?使得新数组为 arr3 = ['100','130']

方法一:

思路:用for循环比较arr1和arr2的每一项,如果相等,就删除

const arr1 = ['', '120', '125', '125', '130', '130', '130', '130', '130'];

const arr2 = ['', '120', '125', '130'];

for (let i = arr1.length - 1; i >= 0; i--) {
    a = arr1[i];
    for (let j = arr2.length - 1; j >= 0; j--) {
        b = arr2[j];
        if (a == b) {
            arr1.splice(i, 1);
            arr2.splice(j, 1);
            break;
        }
    }
}

console.log(arr1);  // ['125','130','130','130','130']

方法二:

思路:将第一个数组存入一个对象,这样就已经去重了;再把第二个数组中的元素当作key从对象中删除。

const m = {};
arr1.forEach(function(al){m[al]=al;})
arr2.forEach(function(bl){delete m[bl];})
console.dir(Object.keys(m))

方法三:

思路:声明一个新的数组arr3,比较arr1和arr2,如果arr1中有和arr2不相等的就放入arr3中,用到了es6中关于数组的新方法findIndex(),稍后会详细的介绍;

const arr1 = ['', '100', '120', '125', '125', '130', '130'];
const arr2 = ['', '120', '125', '125', '130'];
const arr3 = [];
arr1.forEach((a)=>{
    let c = arr2.findIndex(b =>a === b);
    if (c > -1) delete arr2[c];
    else arr3.push(a);
});
console.log(arr3)  //['100', '130']

二, arr1中的每一项都是对象,arr2中的每一项都是元素

const a = [{ id: 15 }, { id: -1 }, { id: 0 }, { id: 3 }, { id: 12.2 }];
const b = [15, 3];

方法一

a.filter(item => { return !b.includes(item.id); });
或
a.filter(item => { return b.indexOf(item.id) === -1; });
 

方法二:

a=a.filter((x)=>b.every((y)=>y!=x.id))

方法三:

const a = [{ id: 15 }, { id: -1 }, { id: 0 }, { id: 3 }, { id: 12.2 }];
const b = [15, 3];
for(index in a){
    if(b.indexOf(a[index]['id'])>=0)
        a.splice(index,1);
}
console.log(a);
或
const result = a.filter(function (item) {
    return b.indexOf(item.id) < 0;
 })

三,arr1中的每一项都是对象,arr2中的每一项也都是对象,现在回到主题

const a = [
    {_id: 1},
    {_id: 2},
    {_id: 3},
];
const b = [
    {_id: 2},
    {_id: 4},
]

解决方法一:

const c = a.filter(x => !b.find(y => y._id === x._id)); // [ { _id: 1 }, { _id: 3} ]

解决方法二:

const c = a.filter(x => b.every(y => y._id !== x._id));

四,介绍一下上面用到的数组实例中的find(), findIndex(), includes()

find()

find()用于找出第一个符合条件的数组成员,它的参数是一个回调函数,所有的数组成员依次执行该回调函数,直到找到第一个返回值为true的成员,然后返回该成员,如果没有的话,返回undefined

[0, 4, -5, -10].find((n) => n < 0);
// -5

上面代码找出数组中第一个小于0的成员

[1, 5, 10, 15].find(function(value, index, arr) {
  return value > 9;
}) 
// 10

find方法的回调函数可以接受三个参数,当前的值,当前的位置和原数组

findIndex()

findIndex()方法的用法与find()方法类似,返回第一个符合条件的数组成员的位置,如果所有成员都不符合,则返回-1.

[1, 5, 10, 15].findIndex(function(value, index, arr) {
  return value > 9;
}) 
// 2

两个方法都可以发现NAN,弥补了数组的indexOf方法的不足

[NaN].indexOf(NaN)
// -1

[NaN].findIndex(y => Object.is(NaN, y))
// 0

indexOf方法无法识别数组的NaN成员,但是findIndex方法可以借助Object.is方法做到

includes()

Array.prototype.includes方法返回一个布尔值,表达某个数组是否包含给定的值,与字符串的includes方法类似

[1, 2, 3].includes(2)     // true
[1, 2, 3].includes(4)     // false
[1, 2, NaN].includes(NaN) // true

该方法的第二个参数表示搜索的起始位置,默认为0,如果第二个参数为负数,表示倒数的位置;如果这是它大于数组长度(比如第二个参数为-4.但是数组长度为3),则会重置为从0开始

[1, 2, 3].includes(3, 3);  // false
[1, 2, 3].includes(3, -1); // true

没有该方法之前,我们通常使用数组的indexOf方法,检查是否包含某个值

if (arr.indexOf(el) !== -1) {
  // ...
}

indexOf方法有两个缺点,一是不够语义化.它的含义是找到参数值的第一个出现位置.所以要去比较是否不等于-1,而是,它内部使用严格相等运算符(===)进行判断,这会导致对NaN的误判

[NaN].indexOf(NaN)
// -1

includes使用的是不一样的判断算法,就没有这个问题。

[NaN].includes(NaN)
// true

参考

github
blog

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,732评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,496评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,264评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,807评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,806评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,675评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,029评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,683评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 41,704评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,666评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,773评论 1 332
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,413评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,016评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,978评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,204评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,083评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,503评论 2 343

推荐阅读更多精彩内容

  • 此文章用于归纳Array的所有方法 在JavaScript中,除了Object,用得最多的可能就是数组Array了...
    moonburn阅读 273评论 1 3
  • 1.Array.from Array.from方法用于将两类对象转为真正的数组:类似数组的对象(array-lik...
    赵然228阅读 658评论 0 0
  • 由于最近都在freecodecamp上刷代码,运用了很多JavaScript数组的方法,因此做了一份关于JavaS...
    2bc5f46e925b阅读 1,960评论 0 16
  • 扩展运算符(spread)是三个点(...) 它好比 rest 参数的逆运算,将一个数组转为用逗号分隔的参数序列。...
    keknei阅读 313评论 0 0
  • 部分列子引用的阮一峰ES6教程中的例子 这篇文章主要是自己经常用得一些方法总结, 想全篇学习es6, 可以看阮一峰...
    有情怀的程序猿阅读 583评论 0 1