Получить все уникальные значения в массиве (удалить дубликаты) для массива / объекта гнезда - PullRequest
0 голосов
/ 30 мая 2018

я знаю, что есть много ответов для уникального массива

, но они не могут работать с массивом массива


, что я хочу, это

исходный массив

[
    1,
    0,
    true,
    undefined,
    null,
    false,
    ['a', 'b', 'c'],
    ['a', 'b', 'c'],
    ['a', 'c', 'b'],
    { a: { b: 2 } },
    { a: { b: 2 } },
    { a: { b: 3 } },
    { a: { b: undefined } },
    { a: {  } },
    { a: { b: 3, c: undefined } },
]

возврат

[
    1,
    0,
    true,
    undefined,
    null,
    false,
    ['a', 'b', 'c'],
    ['a', 'c', 'b'],
    { a: { b: 2 } },
    { a: { b: 3 } },
    { a: { b: undefined } },
    { a: {  } },
    { a: { b: 3, c: undefined } },
]
  • arr-unique может обрабатывать объект [], но не может обрабатывать массив массива
  • Установить тоже нельзя

код ошибки

console.log(array_unique(data));

console.log([...new Set(data)]);

console.log(data.filter(function (el, index, arr)
{
    return index == arr.indexOf(el);
}));

==================

update

я создал модуль для этого array-hyper-unique , но не использовал json stringify, потому что он имеет ошибку, когда valuse равенрегулярное выражение

Ответы [ 4 ]

0 голосов
/ 30 мая 2018

Вы можете использовать рекурсивный подход для объектов и проверять значения.

function check(a, b) {
    if (!a || typeof a !== 'object') {
        return a === b;
    }

    var keys = Object.keys(a);
    return keys.length === Object.keys(b).length
        && keys.every(k => k in b && check(a[k], b[k]));
}

var array = [1, 0, true, undefined, null, false, ['a', 'b', 'c'], ['a', 'b', 'c'], ['a', 'c', 'b'], { a: { b: 2 } }, { a: { b: 2 } }, { a: { b: 3 } }, { a: { b: undefined } }, { a: {} }, { a: { b: 3, c: undefined } }],
    unique = array.reduce((r, b) => (r.some(a => check(a, b)) || r.push(b), r), []);
  
console.log(unique);
.as-console-wrapper { max-height: 100% !important; top: 0; }
0 голосов
/ 30 мая 2018

Попробуйте преобразовать элементы в строку, используя JSON.stringify, и используйте indexOf, чтобы переместить эти элементы в другой массив, только если другой массив не содержит этот элемент.Затем снова используйте map & JSON.parse для преобразования строки в исходный формат

var data = [
  1,
  true, ['a', 'b', 'c'],
  ['a', 'b', 'c'],
  {
    a: {
      b: 2
    }
  },
  {
    a: {
      b: 2
    }
  },
  {
    a: {
      b: 3
    }
  },
]
// Create a new array of only string 
// map will give new array and JSON.stringify will convert elements to string
var newData = data.map(function(item) {
  return JSON.stringify(item)
})
//An empty array which will contain only unique values
var uniques = [];
// loop over the array of stirngs and check
//if that value is present in uniques array
//if not then push the element
newData.forEach(function(item) {
  if (uniques.indexOf(item) === -1) {
    uniques.push(item)
  }
});
//Convert array of string to json
var parsedArr = uniques.map(function(item) {
  return JSON.parse(item)
});
console.log(parsedArr)
0 голосов
/ 30 мая 2018

Причина, по которой метод не работает, заключается в том, что первый ['a', 'b', 'c'], а второй ['a', 'b', 'c'] являются различными объектами , как и первый и второй экземпляры { a: { b: 2 } }.

Из-за этого, даже если вы добавите их к Set, они будут считаться неэквивалентными друг другу и, следовательно, не будут отфильтрованы по уникальности.

Кажется, вы хотитеполучить уникальный массив на основе абсолютных значений в каждом объекте.Один из простых способов сделать это - использовать ES6 Map примерно так:

function uniq(arr) {
  var uniqMap = new Map()
  arr.forEach(element => {
    uniqMap.set(JSON.stringify(element), element)
  })
  return [...uniqMap.values()]
} 

Затем вы можете получить искомый результат:

uniq(data)
//Result: [ 1, true, [ 'a', 'b', 'c' ], { a: { b: 2 } }, { a: { b: 3 } } ]
0 голосов
/ 30 мая 2018

Один простой способ - stringify массивы и объекты для идентификации дубликатов:

const input = [
    1,
    true,
    ['a', 'b', 'c'],
    ['a', 'b', 'c'],
    { a: { b: 2 } },
    { a: { b: 2 } },
    { a: { b: 3 } },
    { a: { b: 3, c: undefined } },
];

const outputSet = new Set();
const stringifiedObjs = new Set();
input.forEach(item => {
  if (typeof item !== 'object') outputSet.add(item);
  else {
    // replace undefineds with something, else they'll be ignored by JSON.stringify:
    const stringified = JSON.stringify(
      item,
      (k, v) => v === undefined ? 'undefined-value' : v
    );
    if (!stringifiedObjs.has(stringified)) {
      outputSet.add(item);
      stringifiedObjs.add(stringified)
    }
  }
});
console.log([...outputSet]);
...