从对象数组的数组中获取唯一字符串

Get unique strings from array of array of objects

我有一个包含对象数组的数组。我想从数组中获取唯一的 属性 值。例如。

var array =     [
  [
    {
      a: 'ggg'
    },
    {
      a: 'kkk'
    }
  ],
  [
    {
      a: undefined
    }
  ],
  [
    {
      a: 'ddd'
    }
  ],
  [
    {
      a: 'ggg'
    }
  ]
];

会 return:

['ggg', 'kkk', 'ddd']

我正在使用下划线库,这是我尝试过的:

var list = _.reduce(arr, function(memo, v, k) {
      memo.concat(_.pluck(v, 'a'));
    return memo;
}, []);

console.log('list is ', list);

console.log(_.uniq(list));

但是它不起作用。 fiddle 是 here.

你可以遍历它并手动创建一个数组

var array = [
  [{
    a: 'ggg'
  }, {
    a: 'kkk'
  }],
  [{
    a: undefined
  }],
  [{
    a: 'ddd'
  }],
  [{
    a: 'ggg'
  }]
];

var result = [];
array.forEach(function(a){
  a.forEach(function(obj){
    if(result.indexOf(obj.a) < 0 && obj.a)
      result.push(obj.a)
  })
})

console.log(result)

var array = [
  [{
    a: 'ggg'
  }, {
    a: 'kkk'
  }],
  [{
    a: undefined
  }],
  [{
    a: 'ddd'
  }],
  [{
    a: 'ggg'
  }]
];

var values = [];

array.map(function(item) {
  return item.map(function(item2) {
    if(item2.a)
      values.push(item2.a);
  });
});

values = values.filter(function(v, i) {
  return values.indexOf(v) == i;
});

console.log(values);

我现在看到其他人已经回答了,但现在我做到了:

https://jsfiddle.net/uc0vot3n/

var array =     [
  [
    {
      a: 'ggg'
    },
    {
      a: 'kkk'
    }
  ],
  [
    {
      a: undefined
    }
  ],
  [
    {
      a: 'ddd'
    }
  ],
  [
    {
      a: 'ggg'
    }
  ]
];

var uniq = [];

array.map(function(obj){
  obj.map(function(item){
        if (uniq.indexOf(item.a) === -1 && item.a){
        uniq.push(item.a);
      }
    });

});

console.log(uniq);

这是一个使用 Underscore 的 flatten, reject, pluck and uniq 的解决方案:

var result = _.chain(array)
    .flatten()
    .pluck('a')
    .reject(_.isUndefined)
    .uniq()
    .value();

使用 ES6,您可以使用 Set

var array = [[{ a: 'ggg' }, { a: 'kkk' }], [{ a: undefined }], [{ a: 'ddd' }], [{ a: 'ggg' }]],
    set = new Set();

array.forEach(a => a.forEach(b => b.a && set.add(b.a)));
console.log([...set]);

繁体有物。

var array = [[{ a: 'ggg' }, { a: 'kkk' }], [{ a: undefined }], [{ a: 'ddd' }], [{ a: 'ggg' }]],
    set = Object.create(null);

array.forEach(function (a) {
    a.forEach(function (b) { 
        b.a && (set[b.a] = true);
    })
});
console.log(Object.keys(set));

这是规范的替代解决方案...它不使用 indexOf 所以我相信它在大型数据集中会更有效一些,因为我们不必在每次添加时都搜索唯一数组一个物品。

var array =     [
  [
    {
      a: 'ggg'
    },
    {
      a: 'kkk'
    }
  ],
  [
    {
      a: undefined
    }
  ],
  [
    {
      a: 'ddd'
    }
  ],
  [
    {
      a: 'ggg'
    }
  ]
];
var map = {};
var uniq = [];

array.forEach(function(items){
    items.forEach(function(item){
        if(item.a) {
            map[item.a] = true;
        }
    });
});

for(var i in map){
    if(map.hasOwnProperty(i)){
        uniq.push(i);
    }
}

console.log(uniq);

为您提供 运行 babel 或最新版本的 nodejs,您不需要 lodash 或下划线。

以下示例依赖于 a 始终是一个字符串,因此它可以用作对象键。

var arr = [
  [{
    a: 'ggg'
  }, {
    a: 'kkk'
  }],
  [{
    a: undefined
  }],
  [{
    a: 'ddd'
  }],
  [{
    a: 'ggg'
  }]
];

var list = Object.keys(
  arr.reduce(function flatten(flattened, subarr) {
    return [...flattened, ...subarr]
  }, [])
  .filter(function hasA(obj) { return obj.a != null })
  .reduce(function putAintoAccumlator(accumulator, obj) {
    return {
      ...accumulator, [obj.a]: true
    }
  }, {})
)
console.log(list)

另一个解决方案是使用 ES6 Set.