请教两个数组对比的问题 - V2EX
waiaan

请教两个数组对比的问题

  •  
  •   waiaan Jun 18, 2024 4496 views
    This topic created in 712 days ago, the information mentioned may be changed or developed.
    const arr1=[a,b,c,d,e,f] const arr2=[d,b,c,a,g,h] 

    需求是:arr2 中的元素如果不在 arr1 中就删除,arr1 中的元素如果不在 arr2 中就要 push 进 arr2 ( arr2 中元素的前后顺序不能变)。 目前想到的就是各遍历一次 arr1 和 arr2 ,有什么更好的方法吗? 谢谢。

    Supplement 1    Jun 18, 2024
    数组中的元素都是对象,不是基本类型的数据。
    arr2 中的元素排列顺序不能变。
    目前做法是两次双层循环:先遍历 arr2 的每个元素,再循环 arr1 看有没有这个元素,没有就删除;接着遍历 arr1 的每个元素,再循环 arr2 看有没有这个元素,没有就从数组末尾添加。
    Supplement 2    Jun 18, 2024
    采用了 13 楼的代码,谢谢。
    20 replies    2024-06-19 16:44:26 +08:00
    FishBear
        1
    FishBear  
       Jun 18, 2024   1
    paopjian
        2
    paopjian  
       Jun 18, 2024
    好奇怪的需求啊,执行完 arr2 不在 arr1 的删除,就是[a,b,c,d],是取交集,那第二步 arr1 元素加入到 arr2,arr2 不就和 arr1 相同了?

    如果是分开的话:
    arr2.filter((x)=>arr1.includes(x))
    arr2.concat(arr1.filter(x=>!arr2.includes(x)))
    renmu
        3
    renmu  
       Jun 18, 2024 via Android
    遍历做哈希,然后遍历比较,时间复杂度是 O(n)
    NessajCN
        4
    NessajCN  
       Jun 18, 2024
    那结果不就是 arr1 吗....还是说 arr1 和 arr2 里有重复元素,所以结果是 arr1 先去重然后加入 arr2 里的重复元素?
    jorneyr
        5
    jorneyr  
       Jun 18, 2024
    使用 HashSet 的快速查找功能,利用空间换时间,效率为 O(n)。
    创建 arr1Set
    创建 arr2Set
    然后再分别遍历 arr2 和 arr1 进行处理。
    waiaan
        6
    waiaan  
    OP
       Jun 18, 2024
    @NessajCN
    @paopjian

    确实结果是 arr1 ,但是不能用 arr1 去替换 arr2 ,因为 arr2 中的元素是对象,同样是 a 元素,唯一标识相同、字段名相同,但是字段的值在 arr2 中有修改过。
    InDom
        7
    InDom  
       Jun 18, 2024
    let arr3 = Array.from(new Set(arr2.filter(x => (new Set(arr1)).has(x)).concat(arr1)))
    waiaan
        8
    waiaan  
    OP
       Jun 18, 2024
    @NessajCN
    @paopjian

    而且顺序也不一样。
    iOCZS
        9
    iOCZS  
       Jun 18, 2024
    老老实实写没错的
    Sawyerhou
        10
    Sawyerhou  
       Jun 18, 2024
    用带顺序的集合试试?顺序控制自建一个比较函数,或者加个序号,然后直接求差集、交集。
    EchoWhale
        11
    EchoWhale  
       Jun 18, 2024
    已经是 O(n)了, 真的还能有更好的吗?
    chihiro2014
        12
    chihiro2014  
       Jun 18, 2024
    这和我做的一个表格表头同步的需求很像
    oamu
        13
    oamu  
       Jun 18, 2024   1
    ``` Javascript
    // 返回用 arr2 中的对象更新 arr1 后的数组,数组按 arr2 中相对顺序排序
    function merge(arr1, arr2) {
    const map = new Map();
    const ans = [];
    arr1.forEach((obj) => map.set(obj.id, obj));
    arr2.forEach((obj) => {
    if (map.has(obj.id)) {
    ans.push(obj);
    map.delete(obj.id);
    }
    });
    return ans.concat(Array.from(map.values()));
    }
    ```
    ZztGqk
        14
    ZztGqk  
       Jun 18, 2024 via iPhone
    整两个 set 做交并补吧
    chendl111
        15
    chendl111  
       Jun 18, 2024
    需求目的就是把 arr1 的元素复制到 arr2 并且删除 arr1 没有的元素。
    那么对两个数组分别 set ,找出差集,双指针扫一遍,复杂度 Onlogn
    Marthemis
        16
    Marthemis  
       Jun 18, 2024
    感觉优化的空间不是很大。

    ```js
    const map1 = new Map()
    const map2 = new Map()
    arr1.forEach(e => {
    map1.set(e.key, e)
    });
    arr2.forEach(e => {
    if (map1.has(e.key)) {
    map2.set(e.key, e)
    }
    });
    arr1.forEach(e => {
    if (!map2.has(e.key)) {
    map2.set(e.key, e)
    }
    });
    console.log(map2.values())
    ```
    xiangyuecn
        17
    xiangyuecn  
       Jun 18, 2024
    // 写了一段 兼容 IE6
    // 只存在一次两层循环
    // 循环的过程中重新建 2 个数组,数组里面放新的对象,对象里面把原始值存进去,加个计数值

    var arr1=["a","b","c","d","e","f","a","b","a","b"] //字符串意思意思,代替相同的对象
    var arr2=["a","b","c","c","c","c","z","z","z","a"]
    var arr11=[],arr22=[];

    for(var i=0;i<arr1.length;i++){
    arr11.push({value:arr1[i], hit:0});
    }
    for(var i=0;i<arr2.length;i++){
    var obj2={value:arr2[i], hit:0};
    arr22.push(obj2);
    for(var j=0;j<arr11.length;j++){ //给 arr11 计数
    var obj1=arr11[j];
    if(obj1.value==obj2.value){ //自行比较两个对象是否相等
    obj1.hit++;
    obj2.hit++;
    }
    }
    }

    //得到已存在的结果
    arr2.length=0; //?
    for(var i=0;i<arr22.length;i++){
    if(arr22[i].hit){
    arr2.push(arr22[i].value);
    }
    }
    //添加缺失的
    for(var i=0;i<arr11.length;i++){
    if(!arr11[i].hit){
    arr2.push(arr11[i].value);
    }
    }

    console.log(arr2);
    YuJianrong
        18
    YuJianrong  
       Jun 19, 2024
    @FishBear 作为作者,我要说明一下 fast-array-diff 不是用在这个场景的。
    fast-array-diff 是为了找出一个有序系列转换到另一个有序系列的步骤。
    这个问题的场景是无序的。
    1835407125
        19
    1835407125  
       Jun 19, 2024
    已经 O(n)了,要是排序好的数组,应该还能优化
    zhj0326
        20
    zhj0326  
       Jun 19, 2024
    arr2.filter(i => !arr1.includes(i)).forEach(i => {
    const index = arr1.indexOf(i);
    if (index !== -1) {
    arr1.splice(index, 1);
    } else {
    arr1.push(i);
    }
    });
    About     Help     Advertise     Blog     API     FAQ     Solana     2952 Online   Highest 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 61ms UTC 00:20 PVG 08:20 LAX 17:20 JFK 20:20
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86