Как сравнить одинаковость записей объектов из 2 массивов и как создать слияние обоих объектов с пользовательскими свойствами одного и того же найденного объекта?

#javascript #arrays #object #merge #comparison

#javascript #массивы #объект #слияние #сравнение

Вопрос:

Я пытаюсь сравнить 2 объекта по их свойству и значениям, строго используя forloop. Если значение «name» или другого свойства совпадает друг с другом, я хочу перевести свойство и значение в значение3.

После регистрации значения3 я хочу, чтобы ответ был таким:

 {
name: 'dog',
surname: 'good',
skills: 'programming',
age: '22'
},
{
name: 'cat',
surname: 'soft',
skills: 'engineer'
age: '12'
},
{
name: 'elephant',
surname: 'big',
skills: 'programming'
age: '23'
}
 

Вот код:

 var values1 = [
    {
    name: 'dog',
    surname: 'good',
    skills: 'programming'
    },
    {
    name: 'cat',
    surname: 'soft',
    skills: 'engineer'
    },
    {
    name: 'elephant',
    surname: 'big',
    skills: 'programming'
    }
]

var values2 = [
    {
    name: 'cat',
    food: 'fish',
    age: '12'
    },
    {
    name: 'elephant',
    food: 'leafs',
    age: '13'
    },
    {
    lastname: 'dog',
    food: 'treats',
    age: '22'
    }
]

// push into this empty object array
var values3 = [{}]

console.log(values3)
 

Комментарии:

1. … разве это не должно быть age: 13 для нужного name: 'elephant' элемента? И по какому правилу происходит age слияние с конечным элементом, но food не происходит? И почему это lastname: 'dog' для values2 последнего элемента?

2. не беспокойтесь о food том, что я просто хочу сравнить name: из массивов, и если они совпадают, то нажмите age на это. но мы видим, что существует также lastname: свойство, но оно по-прежнему имеет то же значение, что и name

3. Как следует предоставить OP действительный общий подход, если вопрос / требования и даже пример кода представлены не так точно? Например, Q. указывает явно… «Если значение «name» или другого свойства совпадает друг с другом» … но затем OP изменяет его в дополнительном комментарии на … «не беспокойтесь о food том, что я просто хочу сравнить name » . Пожалуйста, OP переработайте свой вопрос и укажите точные требования.

4. потому что, если вы посмотрите на свойства обоих, вы увидите, что food этого нет в обоих массивах. Все, что я прошу, это сравнить значения и, если они совпадают, поместить все свойства и значения в один новый массив

5. age too не является частью элементов каждого массива, но он объединяется. Снова. Укажите точные требования.

Ответ №1:

Наиболее общий подход, который удовлетворяет всем требованиям OP, должен основываться на Array.prototype.reduce . Его преимущество заключается в использовании дополнительно переданного необязательного начального значения в качестве настраиваемого объекта коллектора / аккумулятора, который будет содержать всю необходимую дополнительную информацию / функции / результат. Таким образом, можно предоставить повторно используемую функцию с настраиваемым контекстом / средой, которую можно адаптировать к своим потребностям.

 var values1 = [{
  name: 'dog',
  surname: 'good',
  skills: 'programming',
}, {
  name: 'cat',
  surname: 'soft',
  skills: 'engineer',
}, {
  name: 'elephant',
  surname: 'big',
  skills: 'programming',
}];

var values2 = [{
  name: 'cat',
  food: 'fish',
  age: '12'
}, {
  name: 'elephant',
  food: 'leafs',
  age: '13'
}, {
  lastname: 'dog',
  food: 'treats',
  age: '22'
}];

function mergeItemsOfSameEntry(collector, item) {
  const {
    getSameEntryValue,
    getMergeSubType,
    comparisonItems,
    result
  } = collector;

  const itemValue = getSameEntryValue(item);
  const comparisonItem = comparisonItems
    .find(cItem => getSameEntryValue(cItem) === itemValue);

  if (comparisonItem !== null) {
    result.push({
      ...item,
      ...getMergeSubType(comparisonItem),
    });
  }
  return collector;
}

const values3 = values1.reduce(mergeItemsOfSameEntry, {

  getSameEntryValue: item => item.name ?? item.lastname,
  getMergeSubType: ({ age }) => ({ age }),
  comparisonItems: values2,
  result: [],

}).result;

console.log({ values3 }); 
 .as-console-wrapper { min-height: 100%!important; top: 0; } 

Ответ №2:

Если вам просто нужна пара ключ и значение, вы можете сделать что-то вроде этого:

 var values1 = [
    {
    name: 'dog',
    surname: 'good',
    skills: 'programming'
    },
    {
    name: 'cat',
    surname: 'soft',
    skills: 'engineer'
    },
    {
    name: 'elephant',
    surname: 'big',
    skills: 'programming'
    }
]

var values2 = [
    {
    name: 'cat',
    food: 'fish',
    age: '12'
    },
    {
    name: 'elephant',
    food: 'leafs',
    age: '13'
    },
    {
    lastname: 'dog',
    food: 'treats',
    age: '22'
    }
]

// push into this empty object array
var values3 = [];

values1.forEach(eachValue1Obj => {
  const keys = Object.keys(eachValue1Obj);
  keys.forEach(eachKey => {
    values2.forEach(eachValue2Obj => {
      if (
        eachValue1Obj[eachKey] amp;amp;
        eachValue2Obj[eachKey] amp;amp;
        eachValue1Obj[eachKey] === eachValue2Obj[eachKey]
      ) {
        const x = {
          key: eachKey,
          value: eachValue1Obj[eachKey]
        };
        values3.push(x)
      }
    })
  })
})

console.log('Values 3 Array ==>', values3); 

Комментарии:

1. это немного похоже на то, что я спрашиваю. Я хочу, чтобы ответ values3 был { name: 'dog', surname: 'good', skills: 'programming', age: '22' }, { name: 'cat', surname: 'soft', skills: 'engineer' age: '12' }, { name: 'elephant', surname: 'big', skills: 'programming' age: '23' }

2. Без дальнейшего анализа кода и, кроме того, результат не близок к тому, о чем просил OP, я хочу упомянуть, что, на мой взгляд, подход с 3 вложенными forEach циклами уже движется в неправильном направлении.