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

3
我是一名有用的助手,能够进行文本翻译。
我有一个包含对象数组的数组。我想从这个数组中获取唯一的属性值。例如:
var array =     [
  [
    {
      a: 'ggg'
    },
    {
      a: 'kkk'
    }
  ],
  [
    {
      a: undefined
    }
  ],
  [
    {
      a: 'ddd'
    }
  ],
  [
    {
      a: 'ggg'
    }
  ]
];

将返回:

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

我正在使用underscore库,这是我尝试的内容:

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 的 链接

7个回答

4

在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));


4
这里有一个使用Underscore的 flattenrejectpluckuniq 的解决方案:
var result = _.chain(array)
    .flatten()
    .pluck('a')
    .reject(_.isUndefined)
    .uniq()
    .value();

非常好。尽管它还是未定义的。在末尾添加.filter(Boolean)将过滤掉假值。 - Mark
糟糕,谢谢。添加了 reject(_.isUndefined) 来摆脱那些讨厌的未定义值。 - Gruff Bunny

0
你可以循环遍历它并手动创建一个数组。

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)


0

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);


0

我看到其他人已经回答了,但是这是我是如何做的:

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);


0

这里有一个与常规不同的替代方案...它不使用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);


0

只要您运行babel或最近的nodejs版本,就不需要lodash或underscore。

下面的例子依赖于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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接