假设我有一个像这样的数组:
var arr = [
{type:"orange", title:"First"},
{type:"orange", title:"Second"},
{type:"banana", title:"Third"},
{type:"banana", title:"Fourth"}
];
我希望将其分成具有相同类型的对象的数组:
[{type:"orange", title:"First"},
{type:"orange", title:"Second"}]
[{type:"banana", title:"Third"},
{type:"banana", title:"Fourth"}]
但我想一般性地执行此操作,因此没有指定橙色或香蕉的 if 语句
// not like this
for (prop in arr){
if (arr[prop] === "banana"){
//add to new array
}
}
想法? JQuery 和 Underscore 都是可以使用的选项。
Array.reduce(...)
来说是一项简单的工作:
function groupBy(arr, property) {
return arr.reduce(function(memo, x) {
if (!memo[x[property]]) { memo[x[property]] = []; }
memo[x[property]].push(x);
return memo;
}, {});
}
var o = groupBy(arr, 'type'); // => {orange:[...], banana:[...]}
o.orange; // => [{"type":"orange","title":"First"},{"type":"orange","title":"Second"}]
o.banana; // => [{"type":"banana","title":"Third"},{"type":"banana","title":"Fourth"}]
当然,如果你的目标浏览器不支持 ECMAScript 262 第 5 版,那么你必须自己实现“reduce”,或者使用 polyfill 库,或者选择其他答案。
[更新] 这是一个适用于任何版本的 JavaScript 的解决方案:
function groupBy2(xs, prop) {
var grouped = {};
for (var i=0; i<xs.length; i++) {
var p = xs[i][prop];
if (!grouped[p]) { grouped[p] = []; }
grouped[p].push(xs[i]);
}
return grouped;
}
ES6解决方案:
function groupBy(arr, property) {
return arr.reduce((acc, cur) => {
acc[cur[property]] = [...acc[cur[property]] || [], cur];
return acc;
}, {});
}
或者完全ES6fy:
const groupBy = (arr, property) => {
return arr.reduce((acc, cur) => {
acc[cur[property]] = [...acc[cur[property]] || [], cur];
return acc;
}, {});
}
希望对你有帮助!
这假设有一个对象数组:
function groupBy(array, property) {
var hash = {};
for (var i = 0; i < array.length; i++) {
if (!hash[array[i][property]]) hash[array[i][property]] = [];
hash[array[i][property]].push(array[i]);
}
return hash;
}
groupBy(arr,'type') // Object {orange: Array[2], banana: Array[2]}
groupBy(arr,'title') // Object {First: Array[1], Second: Array[1], Third: Array[1], Fourth: Array[1]}
只需构建一个字典,根据标题保存对象即可。你可以这样做:
js
var arr = [
{type:"orange", title:"First"},
{type:"orange", title:"Second"},
{type:"banana", title:"Third"},
{type:"banana", title:"Fourth"}
];
var sorted = {};
for( var i = 0, max = arr.length; i < max ; i++ ){
if( sorted[arr[i].type] == undefined ){
sorted[arr[i].type] = [];
}
sorted[arr[i].type].push(arr[i]);
}
console.log(sorted["orange"]);
console.log(sorted["banana"]);
jsfiddle 演示:http://jsfiddle.net/YJnM6/
打字稿版本。
/**
* Group object array by property
* Example, groupBy(array, ( x: Props ) => x.id );
* @param array
* @param property
*/
export const groupBy = <T>(array: Array<T>, property: (x: T) => string): { [key: string]: Array<T> } =>
array.reduce((memo: { [key: string]: Array<T> }, x: T) => {
if (!memo[property(x)]) {
memo[property(x)] = [];
}
memo[property(x)].push(x);
return memo;
}, {});
export default groupBy;
例如,如果我们不想提及类型,那么我们可以这样实现
var arr = [
{type:"orange", title:"First"},
{type:"orange", title:"Second"},
{type:"banana", title:"Third"},
{type:"banana", title:"Fourth"}
];
const fun = (ar)=>{
let temp ={}
for(e of ar){
!temp[e.type] ? temp[e.type]=[e] : temp[e.type].push(e)
}
return temp
}
console.log(fun(arr))
您还可以使用 https://lodash.com/docs/4.17.15#groupBy
它将满足您的目的
对@Watchmaker的答案进行一些调整,返回数组而不是对象。:
function groupBy(arr, key) {
return arr.reduce((acc, cur) => {
acc[cur[key]] = [...acc[cur[key]] || [], cur];
return acc;
}, []).filter(Boolean);
}
另一个typescript版本
最初受到@denolsson 答案的启发,但我删除了用作键的属性,因为它现在在内部数组中是多余的。
还更改并重命名了其他一些内容,以提高可读性并使 linter 满意)
/**
* Inspired by https://stackoverflow.com/a/53632546/7869582
*/
private groupBy<T>(array: Array<T>, property: keyof T): { [key: string]: Array<T> } {
return array.reduce(
(objectToBeBuilt: { [key: string]: Array<T> }, arrayElem: T) => {
const newOuterIdx = arrayElem[property] as unknown as string;
if (!objectToBeBuilt[newOuterIdx]) {
objectToBeBuilt[newOuterIdx] = [];
}
if (arrayElem[property]) {
delete arrayElem[property];
}
objectToBeBuilt[newOuterIdx]?.push(arrayElem);
return objectToBeBuilt;
},
{} // initial value of objectToBeBuild
);
}
使用示例:
const resultGroupedByCustomer = this.groupBy(result.rows, "customer_id");
对 @denolsson 的 TypeScript 实现 的功能的改进:
/**
* Group an array of objects by a specified property.
* @param {Array<T>} array - The array of objects to group.
* @param {string} property - The property to group the objects by.
* @returns {Object} An object where the keys are the unique values of the specified property and the values are arrays of objects with that property value.
* @template T
*
* @example
* const arr = [{type:"A"}, {type:"A"}, {type:"B"}];
* const result = groupBy(arr, "type");
* console.log(result); // Output: { A: [{type: "A"}, {type: "A"}], B: [{type: "B"}] }
*/
export function groupBy<T>(array: Array<T>, property: string): { [key: string]: Array<T> } {
return array.reduce((memo: { [key: string]: Array<T> }, x: T) => {
memo[x[property]] ||= [];
memo[x[property]].push(x);
return memo;
}, {});
}
和 JavaScript 版本:
export function groupBy(array, property) {
return array.reduce((memo, x) => {
memo[x[property]] ||= [];
memo[x[property]].push(x);
return memo;
}, {});
}
Object.groupBy
方法处理。
const arr = [
{type:"orange", title:"First"},
{type:"orange", title:"Second"},
{type:"banana", title:"Third"},
{type:"banana", title:"Fourth"}
];
const res = Object.groupBy(arr, o => o.type);
console.log(res);