如果至少2具有相同的属性值,则合并数组元素

时间:2016-10-30 14:22:40

标签: javascript arrays merge filtering lodash

我有一系列具有这种结构的对象:

days : string // "mo","tu","we"..
time : string // "9am - 3pm"

当我有2个(或更多)具有相同days值的对象时,有时会发生这种情况。在这种情况下,我需要合并这些项目(更改time值,从这个“相同”项目中加入值)

var array = [{
  days: "mo,tu,we,th",
  time: "9am - 3pm"
}, {
  days: "mo,tu,we,th",
  time: "5pm - 9pm"
}, {
  days: "sa,su",
  time: "9am - 2pm"
}];

var newArr = [];
for (var i = 0; i < array.length; i++) {
  var currItem = array[i];
  
  var mergedArray = [];
  array.forEach(function(el) {
    if (currItem.days == el.days) {
      mergedArray.push(el.time);
    }
  });
  var mergedTime =  mergedArray.join(', ');
  currItem.time = mergedTime;
  if (newArr.filter(function(item) {
    return item.days == currItem.days;
  }).length < 1) {
    newArr.push(currItem);
  }
}

console.log(newArr);

这是我可以看到的,如何合并我的数组项目,但我不喜欢它,因为里面有很多循环。有更优雅的解决方案吗?也许使用lodash。

4 个答案:

答案 0 :(得分:2)

您可以使用_.uniqWith获取预期结果并使用对象引用篡改。

如果您不想修改原始数组,可以将_ .cloneDeep数组传递给_.uniqWith函数。

var arr = [{
  days: "mo,tu,we,th",
  time: "9am - 3pm"
}, {
  days: "mo,tu,we,th",
  time: "5pm - 9pm"
}, {
  days: "sa,su",
  time: "9am - 2pm"
}];

console.log(_.uniqWith(arr, function(a, b) {
  if (a.days === b.days) {
    b.time += ', ' + a.time;
    return true;
  }
}));
<script src="https://cdn.jsdelivr.net/lodash/4.16.4/lodash.min.js"></script>

答案 1 :(得分:1)

使用_.groupBy()按天分组项目,然后将_.mergeWith()应用于每个组:

var array = [{
  days: "mo,tu,we,th",
  time: "9am - 3pm"
}, {
  days: "mo,tu,we,th",
  time: "5pm - 9pm"
}, {
  days: "sa,su",
  time: "9am - 2pm"
}];

var result = _(array)
  .groupBy('days')
  .map(function(days) {
    return _.mergeWith.apply(_, [{}].concat(days, function(obj, src, key) {
        if (key === 'time' && obj && src) {
          return [obj, src].join(', ');
        }
      }));
  })
  .values()
  .value();

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

更漂亮的ES6版本:

var array = [{
  days: "mo,tu,we,th",
  time: "9am - 3pm"
}, {
  days: "mo,tu,we,th",
  time: "5pm - 9pm"
}, {
  days: "sa,su",
  time: "9am - 2pm"
}];

var result = _(array)
  .groupBy('days')
  .map((days) => _.mergeWith({}, ...days, (obj, src, key) => {
    if (key === 'time' && obj && src) {
      return [obj, src].join(', ');
    }
  }))
  .values()
  .value();

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

答案 2 :(得分:1)

你可以在没有任何库的情况下在javascript中使用2个循环:

var array = [{
  days: "mo,tu,we,th",
  time: "9am - 3pm"
}, {
  days: "mo,tu,we,th",
  time: "5pm - 9pm"
}, {
  days: "sa,su",
  time: "9am - 2pm"
}];
tmp = {};
array.forEach(function(item) {
  if (tmp.hasOwnProperty(item.days)) {
    tmp[item.days] = tmp[item.days] + ',' + item.time;
  } else {
    tmp[item.days] = item.time;
  }
});

res = [];
for(var days in tmp) {
  res.push({'days' : days, time: tmp[days]});
}
console.log(res);

答案 3 :(得分:0)

您可以使用此ES6函数,该函数依赖于SetMap个实例来完成其工作:

&#13;
&#13;
function groupDays(array) {
  return Array.from(
    array.reduce((acc, {days, time}) => 
        acc.set(days, (acc.get(days) || new Set()).add(time)),
        new Map()), 
    ([days, times]) => ({ days, time: [...times].join(', ') })
  );
}

// Sample data
var array = [{
  days: "mo,tu,we,th",
  time: "9am - 3pm"
}, {
  days: "mo,tu,we,th",
  time: "5pm - 9pm"
}, {
  days: "sa,su",
  time: "9am - 2pm"
}];

// group
array = groupDays(array);

// result
console.log(array);
&#13;
&#13;
&#13;