Объединение / объединение двух объектов на основе общего ключа (push? сращивание?)

#javascript #arrays #object #merge #lodash

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

Вопрос:

Я пытался использовать push и splice и т. Д. безуспешно. Я надеюсь, вы могли бы дать мне подсказку (или две), чтобы заставить ее работать. Ниже моя проблема, которая не кажется такой сложной … : (

У меня есть 2 объекта:

Объект #1:

 houses:      [ { _id: 1,
                 KLLS: '72797-194155',
                 date : '01/01/1984'},

               { _id: 2,
                 KLLS: '84773-949399',
                 date : '01/01/1984'}
             ]
  

Объект # 2:

 works:       [ { _id: 27,
                 KLLS: '72797-194155',
                 stuff : 'some stuff'},

               { _id: 28,
                 KLLS: '72797-194155', // Note that KLLS key is the same as id:27
                 stuff : 'some stuff'},

               { _id: 29,
                 KLLS: '84773-949399',
                 stuff : 'some stuff'},

               { _id: 30,
                 KLLS: '84773-949399', // Note that KLLS key is the same as id:29
                 stuff : 'some stuff'},

]
  

Чего я хочу добиться, это что-то вроде этого:

 [ { _id: 1,
    KLLS: '72797-194155',
    date : '01/01/1984',
    stuff: 
         [ { _id: 27,
             KLLS: '72797-194155',
             stuff : 'some stuff'},

           { _id: 28,
             KLLS: '72797-194155',
             stuff : 'some stuff'}
         ]
   },

  { _id: 2,
    KLLS: '84773-949399',
    date : '01/01/1984',
    stuff: 
         [ { _id: 27,
             KLLS: '72797-194155',
             stuff : 'some stuff'},

           { _id: 28,
             KLLS: '72797-194155',
             stuff : 'some stuff'}
         ]}
]
  

На самом деле я нахожусь на этом этапе (используя Lodash):

 for(var i = 0; i < houses.length; i  ) {

      // get the KLLS key for each house[i]
      var klls = houses[i].KLLS

     // retrieve the works corresponding to KLLS key for house[i]
     var trvx = _.filter(works, ['KLLS', klls])

    // Merge the two to get the wanted output...
    --> Whatever I try here, nothing works...
        even using splice or push...

}
  

У вас есть какие-либо подсказки, чтобы направить меня в нужное русло?

Ответ №1:

Вы можете это сделать…

 var a = [{
    _id: 1,
    KLLS: '72797-194155',
    date: '01/01/1984'
  },

  {
    _id: 2,
    KLLS: '84773-949399',
    date: '01/01/1984'
  }
]
var b = [{
    _id: 27,
    KLLS: '72797-194155',
    stuff: 'some stuff'
  },

  {
    _id: 28,
    KLLS: '72797-194155', // Note that KLLS key is the same as id:27
    stuff: 'some stuff'
  },

  {
    _id: 29,
    KLLS: '84773-949399',
    stuff: 'some stuff'
  },

  {
    _id: 30,
    KLLS: '84773-949399', // Note that KLLS key is the same as id:29
    stuff: 'some stuff'
  },

]
var newobj = []

var n = a.map(function(el) {
  var temp = []
  b.map(function(el2) {
    if (el.KLLS === el2.KLLS) {
      temp.push(el2)
    }
  })
  el.stuffs = temp
  newobj.push(el)
})

console.log(newobj)  

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

1. Привет, это почти работает :-). Действительно, код должен push преобразовывать элементы с b._id:27 и b._id:28 в._id:1 (полный пример см. В моем исходном сообщении). В то время как ваш фрагмент кода вставляет только b._id:28… У вас есть какие-либо идеи, как это исправить? Еще раз спасибо.

2. @nerotulip Обновлено!. Подумайте о принятии и поддержании ответа!

Ответ №2:

Было бы жаль иметь Lodash и не использовать ни один из его удобных методов для поиска решения.

Поскольку houses JSON помечен как «дома», а works JSON помечен как «works», вы можете сделать следующее, чтобы получить свое решение:

 var res = _.reduce(houses, function (memo, house) {
    return memo.concat(_.extend({}, house, {
        stuff: _.filter(works, {KLLS :house.KLLS})
    }));
}, []);

console.log(res);
  

Идея состоит в том, чтобы reduce houses преобразовать массив в новый массив домов extended с выполненными над ними работами.

Я предпочел создать новый объект вместо изменения оригиналов, чтобы функция могла быть pure максимально возможной.

Ответ №3:

Объедините массивы, сгруппируйте их по KLL, а затем уменьшите массив каждой группы, чтобы получить требуемый объект:

 function combine(arr1, arr2) {
  return _(arr1)
    .concat(arr2) // concat the 2nd array
    .groupBy('KLLS') // group the items by KLLS
    .map(function(group) {
      return group.reduce(function(result, obj) {
        if (obj.date) { // if it's an object with date, merge it with current result and return
          return _.merge(result, obj);
        }

        result.stuff.push(obj);
        return resu<
      }, { stuff: [] }); // initial value is an object with stuff array
    })
    .value(); // end the chain
}

var houses = [{
  _id: 1,
  KLLS: '72797-194155',
  date: '01/01/1984'
}, {
  _id: 2,
  KLLS: '84773-949399',
  date: '01/01/1984'
}];

var works = [{
    _id: 27,
    KLLS: '72797-194155',
    stuff: 'some stuff'
  },

  {
    _id: 28,
    KLLS: '72797-194155',
    stuff: 'some stuff'
  },

  {
    _id: 29,
    KLLS: '84773-949399',
    stuff: 'some stuff'
  },

  {
    _id: 30,
    KLLS: '84773-949399',
    stuff: 'some stuff'
  },
];

var result = combine(houses, works);

console.log(result);  
 <script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.16.2/lodash.min.js"></script>