#javascript #arrays #filter #lodash #ecmascript-5
Вопрос:
итак, у меня есть массив, в котором у ключа есть другой массив объектов, мне нужно создать уникальный массив объектов из этого массива на основе двух уровней ключа и идентификатора пользователя с помощью lodash или vanila JavaScript
например
const data = [
{
values: {
output: [],
}
},
{
values: {
output: [
{ level: 1, userId: "810", },
{ level: 1, userId: "811", },
{ level: 2, userId: "811", },
],
},
},
{
values: {
output: [
{ level: 1, userId: "810", },
],
}
},
{
values: {
output: [
{ level: 1, userId: "810", },
{ level: 3, userId: "810", },
],
}
},
{
values: {
output: [
{ level: 1, userId: "810", },
{ level: 3, userId: "810", },
],
}
}
];
и ожидаемый результат составляет
let output =[
{ level: 1, userId: "810", },
{ level: 1, userId: "811", },
{ level: 2, userId: "811", },
{ level: 3, userId: "810", },
]
Комментарии:
1.Вы можете попробовать
const arr = data.map((obj) => obj.values.output).flat();
const uniq = _.unionBy(arr, JSON.stringify);
Ответ №1:
Вот очень ванильное решение JS. Это не будет быстро для огромных наборов данных, но для наборов, подобных вашему примеру, это не так уж плохо. Сначала он собирает все ваши данные вместе в один массив, а затем создает новый массив без дубликатов. Если вам нужно быть осторожным при перезаписи передаваемых данных, вы можете сначала их клонировать.
function mergeAllData(data) {
var allData = [];
for (var i in data) {
allData = allData.concat(data[i].values.output);
}
return allData;
}
function filterDuplicates(allData) {
var ret = [];
for (var i in allData) {
var current = allData[i];
ret.push(current);
for (var j in allData) {
if (isADuplicate(current, allData[i])) {
allData.splice(j, 1);
}
}
}
return ret;
}
function isADuplicate(t1, t2) {
return t1.level === t2.level amp;amp; t1.userId === t2.userId;
}
console.log(filterDuplicates(mergeAllData()));
Ответ №2:
Получите массив всех output
свойств с _.flatMap()
помощью (или Array.flatMap()
, а затем используйте _.uniqBy()
для получения только уникальных элементов. В _.uniqBy()
обратном вызове возвращайте пользовательское значение путем объединения level
и userId
в одну строку.
ES5:
var data = [{"values":{"output":[]}},{"values":{"output":[{"level":1,"userId":"810"},{"level":1,"userId":"811"},{"level":2,"userId":"811"}]}},{"values":{"output":[{"level":1,"userId":"810"}]}},{"values":{"output":[{"level":1,"userId":"810"},{"level":3,"userId":"810"}]}},{"values":{"output":[{"level":1,"userId":"810"},{"level":3,"userId":"810"}]}}];
var result = _.uniqBy(
_.flatMap(data, function(o) { return o.values.output; }),
function(o) { return o.level '-' o.userId; }
);
console.log(result);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.21/lodash.min.js" integrity="sha512-WFN04846sdKMIP5LKNphMaWzU7YpMyCU245etK3g/2ARYbPK9Ub18eG ljU96qKRCWh quCY7yefSmlkQw1ANQ==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
ES6:
const data = [{"values":{"output":[]}},{"values":{"output":[{"level":1,"userId":"810"},{"level":1,"userId":"811"},{"level":2,"userId":"811"}]}},{"values":{"output":[{"level":1,"userId":"810"}]}},{"values":{"output":[{"level":1,"userId":"810"},{"level":3,"userId":"810"}]}},{"values":{"output":[{"level":1,"userId":"810"},{"level":3,"userId":"810"}]}}];
const result = _.uniqBy(
_.flatMap(data, o => o.values.output),
o => `${o.level}-${o.userId}`
);
console.log(result);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.21/lodash.min.js" integrity="sha512-WFN04846sdKMIP5LKNphMaWzU7YpMyCU245etK3g/2ARYbPK9Ub18eG ljU96qKRCWh quCY7yefSmlkQw1ANQ==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
Комментарии:
1. У него это помечено как ecmascript-5
2. Спасибо. Изменения незначительны, потому что lodash выполняет тяжелую работу. Странно то, что он использует а
const
и аlet
в вопросе.