2016-10-30 68 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);

相關問題