suchen

Heim  >  Fragen und Antworten  >  Hauptteil

javascript – Problem bei der Array-Deduplizierung

Angenommen, es gibt jetzt eine Reihe von Objekten

arr=[
    {
    id:1,
    content:'a'
    },{
    id:2,
    content:'b'
    },{
    id:2,
    content:'c'
    },{
    id:3,
    content:'d'
    },{
    id:3,
    content:'e'
    },{
    id:3,
    content:'f'
    },{
    id:3,
    content:'g'
    },{
    id:4,
    content:'h'
    },
]

Ich möchte dieselbe ID entfernen und das letzte Element jeder ID behalten

arr=[
    {
    id:1,
    content:'a'
    },{
    id:2,
    content:'c'
    },{
    id:3,
    content:'g'
    },{
    id:4,
    content:'h'
    },
]

Gibt es einen besseren Weg? .

女神的闺蜜爱上我女神的闺蜜爱上我2705 Tage vor642

Antworte allen(9)Ich werde antworten

  • 漂亮男人

    漂亮男人2017-06-28 09:26:12

    按惯例,ES6 代码

    const result = arr.reduce((r, t) => {
        // 在结果中查找 index,
        // 如果找到,更新该位置的对象引用
        // 找到则加一个
        var i = r.findIndex(m => m.id === t.id);
        if (i >= 0) {
            r[i] = t;
        } else {
            r.push(t);
        }
        return r;
    }, []);

    这里有一个问题,findIndex 至少有两个浏览器不支持,所以,如果不支持的话,只好自己写一个

    Array.prototype.findIndex = Array.prototype.findIndex || function(predicate) {
        for (let i = 0; i < this.length; i++) {
            if (predicate(this[i])) {
                return i;
            }
        }
        return -1;
    };

    其它解法

    经典解决,用 Map

    因为 id 不是字符串,所以使用 ES6 的 Map 类。当数据量大的时候,使用查找表,比在列表中线性查找,效率会有显著的提升。

    const result = arr
        .reduce((m, t) => {
            const { map, list } = m;
            var index = map.get(t.id);
            if (index >= 0) {
                list[index] = t;
            } else {
                map.set(t.id, list.length);
                list.push(t);
            }
            return m;
        }, {
            map: new Map(),
            list: []
        })
        .list;

    其实也可以用对象来代替 map,至少在这个用例中不会有问题。因为没用 es6 特性,索性完全使用 es5 语法。代码结构和逻辑与上面那段一样

    var result = arr
        .reduce(function(m, t) {
            var index = m.map[t.id];
            if (index >= 0) {
                m.list[index] = t;
            } else {
                m.map[t.id] = m.list.length;
                m.list.push(t);
            }
            return m;
        }, {
            map: {},
            list: []
        })
        .list;

    怪异解法,利用整数 id

    因为是整数 id,所以可以直接按这个 id 放在数组中。如果遇到相同 id,直接就替换了。如果 id 不连续,最后需要把空元素过滤掉

    var result = arr
        .reduce(function(r, t) {
            r[t.id] = t;
            return r;
        }, [])
        .filter(function(t) { return t; });

    这种解法还有个问题,不能保持原数组的元素顺序。然后肯定会有人想到,用 Map 的那个解法也可以把代码精减成类似的代码,而不需要搞那么复杂,当然它也同样可能失去原有顺序

    const map = arr
        .reduce((m, t) => {
            m.set(t.id, t);
            return m;
        }, new Map());
    
    const result = [...map.values()];

    注:以上所有代码均实际运行通过,运行环境 Node v8.1.2

    Antwort
    0
  • 某草草

    某草草2017-06-28 09:26:12

    var result = arr.filter(function(val, index) {
        /**
         * 使用arr.slice(index + 1)获取从当前索引下一个元素到数组最后一个元素组成的数组
         * 使用findIndex在当前项的后面选项中查找是否有和当前项id值相同的选项
         */
        var index = arr.slice(index + 1).findIndex(function(item) {
             return item.id === val.id;
        });
        // 如果为-1,则说明后面没有同名id了,所以这一项可以返回
        return index === -1;
    });
    console.log(result);

    使用箭头函数简化如下:

    var result = arr.filter((val, index) => arr.slice(index + 1).findIndex(item => item.id === val.id) === -1);
    console.log(result);

    Antwort
    0
  • 仅有的幸福

    仅有的幸福2017-06-28 09:26:12

    这里面已经有很多答案了,不过没有提到Array的内置函数reduceRight,实际上题主的需求,要求保留相同id的最后一位,用reduceRight实现起来很方便。

    arr.reduceRight((r,v)=>{
        if(!r[0].has(v.id)) r[0].add(v.id) && r[1].unshift(v)
        return r
    },[new Set,[]])[1]

    reduceRight从你原数组尾部开始循环的,我这里的初始值是个数组,r[0]用来存放id的Set,r[1]存放结果数组,如果Set里没有id,那么就添加这个id到Set,并且把这一项放在结果数组的头部。

    最终很容易的实现了题主的需求,而且顺序也能保证。

    Antwort
    0
  • 曾经蜡笔没有小新

    曾经蜡笔没有小新2017-06-28 09:26:12

    function uniq(arr) {
        var idArr = [],arr2 = []
        for (var i = 0, len = arr.length; i < len; i++) {
            if (arr[i].id in idArr) {
                arr2.pop()
                arr2.push(arr[i])
            } else {
                idArr.push(arr[i].id)
                arr2.push(arr[i])
            }
        }
        return arr2
    }

    亲测有效

    Antwort
    0
  • 伊谢尔伦

    伊谢尔伦2017-06-28 09:26:12

    arr = [ { id: 1, content: 'a' },
            { id: 2, content: 'b' },
            { id: 2, content: 'c' },
            { id: 3, content: 'd' },
            { id: 3, content: 'e' },
            { id: 3, content: 'f' },
            { id: 3, content: 'g' },
            { id: 4, content: 'h' } ]
            
    tmp = []
    for(k in arr){tmp[arr[k]['id']] = arr[k]['content']}
    
    arr = []
    for(k in tmp){arr.push({'id':+k, 'content':tmp[k]})}
    
    console.log(arr)
    [ { id: 1, content: 'a' },
      { id: 2, content: 'c' },
      { id: 3, content: 'g' },
      { id: 4, content: 'h' } ]

    Antwort
    0
  • 滿天的星座

    滿天的星座2017-06-28 09:26:12

    let newArr = [],

        result = [],
        status = false,
        lastResult = []
    for (let i = arr.length - 1; i >= 0; i--) {
        newArr.push(arr[i])
    }
    for (let i = 0, len = newArr.length; i < len; i++) {
        if (result.length == 0) {
            result.push(newArr[0])
        }
        for (let j = 0; j < result.length; j++) {
            if (newArr[i].id == result[j].id) {
                console.log(newArr[i])
                status = true
            }
        }
        if (!status) {
    
            result.push(newArr[i])
        }
        status = false
    
    }
    for (let i = result.length - 1; i >= 0; i--) {
        lastResult.push(result[i])
    }
    console.log(lastResult) //为去掉相同的id 然后保留各个id的最后一项

    Antwort
    0
  • 学习ing

    学习ing2017-06-28 09:26:12

    var arr = [ ... ]; // 这个为给定的数组
    var obj = {}; // 定义一个对象存储
    
    arr.forEach(function(v) {
        obj[v.id] = v;
        // 不管如何,直接将数组赋值给obj中下标为v.id的项,这样对应的v.id的值到最后必然是同ID最后一项
    });
    
    // 下面考虑兼容性给出新语法和常规语法
    // 新语法,Object.values部分浏览器版本不支持
    var result = Object.values(obj);
    // 常规语法,用Array.map实现Object.values的效果
    var result = Object.keys(obj).map(function(id) {
        return obj[id];
    });

    Antwort
    0
  • 天蓬老师

    天蓬老师2017-06-28 09:26:12

    参考一下

    Array.from(arr.reduce((map, el) => map.set(el.id, el), new Map()).values())

    Antwort
    0
  • 为情所困

    为情所困2017-06-28 09:26:12

    你可以参考我博客写的,我博客上写了8中方法。http://alfierichou.top/2017/0...

    Antwort
    0
  • StornierenAntwort