Converting lodash _.uniqBy() to native javascript

后端 未结 4 675
傲寒
傲寒 2021-01-02 14:03

Here in this snippet i am stuck as in _.uniqBy(array,iteratee),this

  • iteratee can be a function or a string at the same time
相关标签:
4条回答
  • 2021-01-02 14:10

    I'm running my code through Webpack via CreateReactApp, it must be using a polyfill for spread that uses slice. Here's what I did instead, a variation of @oridori's answer:

    const uniqBy = (arr: any[], predicate: (item: any) => string) => {
      const cb = typeof predicate === 'function' ? predicate : (o) => o[predicate];
      const result = [];
      const map = new Map();
    
      arr.forEach((item) => {
        const key = (item === null || item === undefined) ? item : cb(item);
    
        if (!map.has(key)) {
          map.set(key, item);
          result.push(item);
        }
      });
    
      return result;
    };
    
    0 讨论(0)
  • 2021-01-02 14:12

    You could use a sort ordered by name and a filter based on the neighborhood comparison like this :

    var sourceArray = [ { id: 1, name: 'bob' },
      { id: 1, name: 'bill' },
      { id: 1, name: 'bill' } ,
      {id: 2,name: 'silly'},
      {id: 2,name: 'billy'}]
    
    var uniqBy = (inputArray, callback) => inputArray.sort((a,b) => callback(a) > callback(b))
    .filter((x,i,arr) => i === arr.length -1 ? true : callback(x) !== callback(arr[i+1]));
    var inputFunc = item => item.name;
    
    
    var destArray = uniqBy(sourceArray, inputFunc)
    console.log('destArray', destArray)

    0 讨论(0)
  • 2021-01-02 14:20

    An ES6 uniqBy using Map with a complexity of O(n):

    const uniqBy = (arr, predicate) => {
      const cb = typeof predicate === 'function' ? predicate : (o) => o[predicate];
      
      return [...arr.reduce((map, item) => {
        const key = (item === null || item === undefined) ? 
          item : cb(item);
        
        map.has(key) || map.set(key, item);
        
        return map;
      }, new Map()).values()];
    };
    
    const sourceArray = [ 
      { id: 1, name: 'bob' },
      { id: 1, name: 'bill' },
      null,
      { id: 1, name: 'bill' } ,
      { id: 2,name: 'silly'},
      { id: 2,name: 'billy'},
      null,
      undefined
    ];
    
    console.log('id string: ', uniqBy(sourceArray, 'id'));
    
    console.log('name func: ', uniqBy(sourceArray, (o) => o.name));

    0 讨论(0)
  • 2021-01-02 14:22

    Refactored @ori-drori's solution and removed

    1. undefined
    2. null
    3. extra numbers in mixed array
    4. return [] if first param is not Array

    const uniqBy = (arr, predicate) => {
      if (!Array.isArray(arr)) { return []; }
    
      const cb = typeof predicate === 'function' ? predicate : (o) => o[predicate];
    
      const pickedObjects = arr
        .filter(item => item)
        .reduce((map, item) => {
            const key = cb(item);
    
            if (!key) { return map; }
    
            return map.has(key) ? map : map.set(key, item);
        }, new Map())
        .values();
     
      return [...pickedObjects];
    };
    
    const a = [ 
      12,
      undefined,
      { id: 1, name: 'bob' },
      null,
      { id: 1, name: 'bill' },
      null,
      undefined
    ];
    
    const b = [ 
      12,
      { id: 1, name: 'bob' },
      { id: 1, name: 'bill' },
    ];
    
    uniqBy(a, 'name');
    uniqBy(b, Math.floor);
    uniqBy([2.1, 1.2, 2.3], Math.floor);

    0 讨论(0)
提交回复
热议问题