2016-10-30 70 views
3

我有对象数组中,具有这样的结构:当我有2(或甚至更多)具有相同days值对象发生合并数组的元素,如果至少2具有相同的属性值

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

有些时候。在这种情况下,我需要合并这个项目(改变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。

+0

你确定你想吗?如果你加入这样的时代,似乎这些时间适用于同一个对象的所有日子,这是不正确的。 – trincot

+0

@trincot,为什么?我得到一种格式的回复 - 分组日期和时间(所有对象都有这个时间)......但是如果某些商店在某些日子有休息时间,那么我在那一天得到2倍的“时间”:如果在星期一商店从早上9点到下午2点工作,然后休息,然后再从下午4点到晚上9点工作 - 响应将返回2个对象'[{days:“mo”,time:“9am - 2pm”},{days: “mo”,时间:“4pm - 9pm”}]'。所以我认为我正确地思考,不是吗? – demo

+0

在这个例子中,它是可以的,但是如果你在第一个对象的'days'属性中提到了多个天,并且将它与单日第二个对象结合:'[{days:“mo,tu”,time:“9am - 2pm“},{days:”mo“,time:”4pm - 9pm“}]',你会怎么做?这个结果会令周二下午感到困惑:'[{days:“mo,tu”,time:“9am - 2pm,4pm - 9pm”}] – trincot

回答

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

只有一种方法使用。整齐!看起来你不需要'返回true',所以它只有3行代码:O –

+1

@ bfred.it谢谢!不幸的是,你需要return语句来删除重复的条目(不需要返回false,因为undefined是一个虚假值,因此足以将该元素标记为不重复)。 – acontell

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>

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);

+0

由于'lodash'已经在项目中,所以使用这种方法并不是问题。这就是为什么我写了关于'lodash'的问题 – demo

+3

有时候库的开销是不需要的(如果有人会搜索一个没有lodash的解决方案,他可以使用这个):) – Dekel

0

您可以使用此ES6功能,它依赖于SetMap情况下做的工作:

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);

相关问题