Как пропустить повторяющийся объект, используя значение свойства в функции Reduce в JavaScript? - PullRequest
0 голосов
/ 17 мая 2019

У меня есть массив таких объектов:

// other properties of the object omitted for brevity
// this array can potentially contain upto 50 objects like this
var myArray = [{url: 'http://linkA'}, {url: 'http://linkB'}, {url: 'http://linkA'}]

Я пытаюсь применить функцию Reduce для создания нового объекта, подобного этому:

  var newArray = myArray.reduce(function(acc, current, index){
  var newObj = {};
  newObj['strata']  = 'kit';
  newObj['href'] = current['url'];
  acc.push(newObj);
  return acc;  
}, [])

Но я нехотите включить дубликаты объектов («дубликаты» проверены с использованием свойства «url» объекта).Как я могу изменить мою функцию приведения, чтобы пропустить такие объекты и создать

[{strata: kit, href: 'http://linkA'}, {strata: kit, href: 'http://linkB'}]

Edit : Извините, я забыл упомянуть, что это устаревший код.Я не могу использовать такие функции, как «Установить» и «некоторые»

Ответы [ 6 ]

2 голосов
/ 17 мая 2019

Использование some:

var myArray = [{url: 'http://linkA'}, {url: 'http://linkB'}, {url: 'http://linkA'}];

var newArray = myArray.reduce(function(acc, { url }, index) {
  if (Object.values(acc).some(({ href }) => href === url)) {
    return acc;
  }
  acc.push({
    strata: 'kit',
    href: url
  });
  return acc;
}, [])

console.log(newArray);
1 голос
/ 17 мая 2019

Вы можете получить все уникальные url s, используя Set.Затем создайте объекты, используя map и Сокращенные имена свойств :

const myArray = [{url: 'http://linkA'}, {url: 'http://linkB'}, {url: 'http://linkA'}],
      uniqueUrls = new Set(myArray.map(a => a.url)),
      strata = "kit",
      output = [...uniqueUrls].map(href => ({ strata, href }));

console.log(output)

Если вы не можете использовать функции ES2015 +, вы можете иметь объект в качестве аккумулятора и каждый уникальный url в качестве ключа.Таким образом, вы получите только один url в аккумуляторе.Затем переберите объект и получите значения объединенного объекта

var myArray = [{url: 'http://linkA'}, {url: 'http://linkB'}, {url: 'http://linkA'}];

var merged = myArray.reduce(function(acc, current) {
  acc[current.url] = current;
  return acc;
}, {})

var output = [];

for(var key in merged) {
  output.push(merged[key])
}

console.log(output)

Вот как будет выглядеть объединенный объект:

{
  "http://linkA": {
    "url": "http://linkA"
  },
  "http://linkB": {
    "url": "http://linkB"
  }
}
1 голос
/ 17 мая 2019

Вы можете проверить наличие дубликатов, используя some() до push()

var myArray = [{url: 'http://linkA'}, {url: 'http://linkB'}, {url: 'http://linkA'}]

var newArray = myArray.reduce(function(acc, current, index){
  var newObj = {};
  newObj['strata']  = 'kit';
  newObj['href'] = current['url'];
  if(!acc.some(x => x.href === current.url)) acc.push(newObj);
  return acc;  
}, [])

console.log(newArray)

Более короткая версия кода будет

var myArray = [{url: 'http://linkA'}, {url: 'http://linkB'}, {url: 'http://linkA'}]

const res=  myArray.reduce((ac,a) => 
                  (!ac.some(x => x.href === a.url) && 
                  ac.push({strata:'kit',href:a.url}),
                  ac),
             []);

console.log(res)
1 голос
/ 17 мая 2019

Вы можете проверить, существует ли сначала url в любом из объектов в аккумуляторе:

var myArray = [{
  url: 'http://linkA'
}, {
  url: 'http://linkB'
}, {
  url: 'http://linkA'
}];

var newArray = myArray.reduce(function(acc, { url }, index) {
  if (acc.some(obj => obj.href === url)) {
    return acc;
  }
  acc.push({
    strata: 'kit',
    href: url
  });
  return acc;
}, [])

console.log(newArray);

Для сложности O(N) вместо O(N^2) добавьте каждый URL к внешнему Set (чей поиск O(1), а не O(N) для Array.prototype.some):

var myArray = [{
  url: 'http://linkA'
}, {
  url: 'http://linkB'
}, {
  url: 'http://linkA'
}];

const urls = new Set();
var newArray = myArray.reduce(function(acc, { url }, index) {
  if (urls.has(url)) {
    return acc;
  }
  urls.add(url);
  acc.push({
    strata: 'kit',
    href: url
  });
  return acc;
}, [])

console.log(newArray);

Или, в ES5, использовать объект вместо Set:

var myArray = [{
  url: 'http://linkA'
}, {
  url: 'http://linkB'
}, {
  url: 'http://linkA'
}];

var urls = {};
var newArray = myArray.reduce(function(acc, obj, index) {
  var url = obj.url;
  if (urls[url]) {
    return acc;
  }
  urls[url] = true;
  acc.push({
    strata: 'kit',
    href: url
  });
  return acc;
}, [])

console.log(newArray);
0 голосов
/ 17 мая 2019

Я бы наверное

  • Используйте Set (или объект) для отслеживания URL-адресов, которые я уже видел, и
  • Используйте инициализатор объекта вместо трех операторов для создания нового объекта и
  • Используйте простой цикл вместо reduce

Но вот версия, все еще использующая reduce:

var myArray = [{url: 'http://linkA'}, {url: 'http://linkB'}, {url: 'http://linkA'}]
var known = new Set();
var newArray = myArray.reduce(function(acc, current, index){
  if (!known.has(current.url)) {
    acc.push({
      strata: 'kit',
      href: current.url
    });
    known.add(current.url);
  }
  return acc;  
}, [])
console.log(newArray);

Вот более простая версия с использованием цикла:

var myArray = [{url: 'http://linkA'}, {url: 'http://linkB'}, {url: 'http://linkA'}]
var known = new Set();
var newArray = [];
for (const current of myArray) {
  if (!known.has(current.url)) {
    newArray.push({
      strata: 'kit',
      href: current.url
    });
    known.add(current.url);
  }
}
console.log(newArray);

Если вы не можете использовать функции ES2015 +, такие как Set и for-of, вы можете использовать объект для отслеживания URL-адресов и простой цикл for:

var myArray = [{url: 'http://linkA'}, {url: 'http://linkB'}, {url: 'http://linkA'}]
var known = Object.create(null); // An object with no prototype
var newArray = [];
for (var index = 0; index < myArray.length; ++index) {
  var current = myArray[index];
  if (!known[current.url]) {
    newArray.push({
      strata: 'kit',
      href: current.url
    });
    known[current.url] = true;
  }
}
console.log(newArray);
0 голосов
/ 17 мая 2019

создайте Set, который принимает отображенную версию вашего массива только с URL-адресами в наборе. - Set де-дублирует ваш массив, а затем вы можете создать новый массив из набора с добавленным к нему свойством strata..

const myArray = [{url: 'http://linkA'}, {url: 'http://linkB'}, {url: 'http://linkA'}]
const s = new Set(myArray.map(({ url }) => url))

const newArray = [...s].map(url => ({
  url,
  strata: 'kit'
}))
console.log(newArray)

Если вы хотите, чтобы ваш окончательный массив объектов был более динамичным.Создайте функцию, которая принимает параметр, который вы хотите восстановить, и параметры, которые вы хотите вставить в завершенный объект.

const DE_DUPE_INSERT = (array, flag, insert) => {
  const s = new Set(array.map(item => item[flag]))
  return [...s].map(property => ({
    [flag]: property,
    ...insert
  }))
}
const ARR = [{url: 'http://linkA'}, {url: 'http://linkB'}, {url: 'http://linkA'}]
const de_duped = DE_DUPE_INSERT(ARR, 'url', {strata: 'kit', foo: 'bar'})

console.log(de_duped)

< es6

var DE_DUPE_INSERT = function (array, flag, insert) {
  var de_duped = []
  array.forEach(function (item) {
    if (de_duped.indexOf(item[flag]) === -1) de_duped.push(item[flag])
  })
  
  return de_duped.map(function (property) { 
    var obj = {}
    obj[flag] = property
    Object.keys(insert).forEach(function (key) {
      obj[key] = insert[key]
    })
    return obj
  })
}
var ARR = [{url: 'http://linkA'}, {url: 'http://linkB'}, {url: 'http://linkA'}]
var de_duped = DE_DUPE_INSERT(ARR, 'url', {strata: 'kit', foo: 'bar'})

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