Как включить значения только один раз в массив объектов? - PullRequest
3 голосов
/ 14 июля 2020

У меня есть этот массив объектов.

[
  {
    tier1: "Normal",
    tier2: "none",
    tier3: "none",
    tier4: "none",
    tier5: "none",
  },
  {
    tier1: "Urgent",
    tier2: "GCC & Labour",
    tier3: "new",
    tier4: "Cancellation",
    tier5: "Cancellation",
  },
  {
    tier1: "Urgent",
    tier2: "Foreigner",
    tier3: "renew",
    tier4: "Cancellation",
    tier5: "none",
  },
]

Мне нужно получить значения tier1, tier2, tier3 tier4 и tier5 только один раз.

Итак, предположим, что в приведенном выше примере tier1 имеет Normal один раз и Urgent два раза, поэтому он будет удален в следующем элементе. tier5 имеет none в первом элементе, поэтому будет извлечен из последнего элемента, поскольку он уже существует.

Результат будет

[
  {
    tier1: "Normal",
    tier2: "none",
    tier3: "none",
    tier4: "none",
    tier5: "none",
  },
  {
    tier1: "Urgent",
    tier2: "GCC & Labour",
    tier3: "new",
    tier4: "Cancellation",
    tier5: "Cancellation",
  },
  { tier2: "Foreigner", tier3: "renew" },
]

Ответы [ 4 ]

1 голос
/ 14 июля 2020

Поддерживает Set значений для каждого ключа в объекте. Используйте map и получите обновленный отфильтрованный объект. (обновленным объектом будут ключи, которых еще нет)

const all = {};

const updateObject = (obj) =>
  Object.fromEntries(
    Object.entries(obj).filter(([key, value]) => {
      if (!(key in all)) {
        all[key] = new Set();
      }
      const result = !all[key].has(value);
      all[key].add(value);
      return result;
    })
  );

const output = arr => arr.map(updateObject);

data = [
  {
    tier1: "Normal",
    tier2: "none",
    tier3: "none",
    tier4: "none",
    tier5: "none",
  },
  {
    tier1: "Urgent",
    tier2: "GCC & Labour",
    tier3: "new",
    tier4: "Cancellation",
    tier5: "Cancellation",
  },
  {
    tier1: "Urgent",
    tier2: "Foreigner",
    tier3: "renew",
    tier4: "Cancellation",
    tier5: "none",
  },
];



console.log(output(data));
1 голос
/ 14 июля 2020

Что-то вроде этого должно дать результаты, которые вы ищете.

Время выполнения, используя набор для отслеживания дубликатов, должно быть O(kN), где N - количество записей в массиве, а k - количество ключей в каждом объекте (здесь 5), что является наиболее жесткой границей в этой проблеме.

const data = [{
    tier1: "Normal",
    tier2: "none",
    tier3: "none",
    tier4: "none",
    tier5: "none",
  },
  {
    tier1: "Urgent",
    tier2: "GCC & Labour",
    tier3: "new",
    tier4: "Cancellation",
    tier5: "Cancellation",
  },
  {
    tier1: "Urgent",
    tier2: "Foreigner",
    tier3: "renew",
    tier4: "Cancellation",
    tier5: "none",
  },
]

const removeDuplicates = (arr) => {

  // retains a set of values for every key
  elementSet = {};
  return arr.map((elem) => {
    const newObj = {};

    // iterate over all the keys
    for (const key of Object.keys(elem)) {
      const value = elem[key];

      if (!(key in elementSet)) {
        // instantiate the set for the given key
        elementSet[key] = new Set();
      }

      if (!elementSet[key].has(value)) {
        // it hasn't been used before, so we can use it, but we'll add to the set for the future
        newObj[key] = elem[key];
        elementSet[key].add(elem[key]);
      }

    }
    return newObj;
  })
}


console.log(removeDuplicates(data))
1 голос
/ 14 июля 2020

Если речь идет о повторном сопоставлении исходного массива с отфильтрованными копиями элементов-объектов на основе ранее замеченных пар ключ / значение, вы можете использовать Array.prototype.map() в сочетании с Object.assign() для переназначения вместе с Object.keys() вместе с Array.prototype.reduce() для фильтрации:

const src = [{tier1:"Normal",tier2:"none",tier3:"none",tier4:"none",tier5:"none",},{tier1:"Urgent",tier2:"GCC & Labour",tier3:"new",tier4:"Cancellation",tier5:"Cancellation",},{tier1:"Urgent",tier2:"Foreigner",tier3:"renew",tier4:"Cancellation",tier5:"none",},],

simplify = (arr, hashMap = []) =>
  arr.map(o => Object.assign(
    {},
    ...Object.keys(o).reduce((r,key) => {
      const hash = key+'\ud8ff'+o[key]
      if(!hashMap.includes(hash)){
        r.push({[key]:o[key]})
        hashMap.push(hash)
      }
      return r
    }, [])
  ))

console.log(simplify(src))
.as-console-wrapper{min-height:100%;}
0 голосов
/ 14 июля 2020

const data = [{
    tier1: "Normal",
    tier2: "none",
    tier3: "none",
    tier4: "none",
    tier5: "none",
  },
  {
    tier1: "Urgent",
    tier2: "GCC & Labour",
    tier3: "new",
    tier4: "Cancellation",
    tier5: "Cancellation",
  },
  {
    tier1: "Urgent",
    tier2: "Foreigner",
    tier3: "renew",
    tier4: "Cancellation",
    tier5: "none",
  },
]

let t1 = [],
  t2 = [],
  t3 = [],
  t4 = [],
  t5 = []

data.forEach(d => {
  if (!t1.includes(d.tier1)) t1.push(d.tier1)
  if (!t2.includes(d.tier2)) t2.push(d.tier2)
  if (!t3.includes(d.tier3)) t3.push(d.tier3)
  if (!t4.includes(d.tier4)) t4.push(d.tier4)
  if (!t5.includes(d.tier5)) t5.push(d.tier5)
})

let result = []
for (let i = 0; i < data.length; i++) {
  let object = {}
  if (t1[i]) object.tier1 = t1[i]
  if (t2[i]) object.tier2 = t2[i]
  if (t3[i]) object.tier3 = t3[i]
  if (t4[i]) object.tier4 = t4[i]
  if (t5[i]) object.tier5 = t5[i]
  result.push(object)
}

console.log(result)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...