키로 개체 배열을 그룹화하는 방법
객체 키로 객체 배열을 그룹화 한 다음 그룹화를 기반으로 새 객체 배열을 만드는 방법을 알고있는 사람이 있습니까? 예를 들어, 자동차 객체의 배열이 있습니다.
var cars = [
{
'make': 'audi',
'model': 'r8',
'year': '2012'
}, {
'make': 'audi',
'model': 'rs5',
'year': '2013'
}, {
'make': 'ford',
'model': 'mustang',
'year': '2012'
}, {
'make': 'ford',
'model': 'fusion',
'year': '2015'
}, {
'make': 'kia',
'model': 'optima',
'year': '2012'
},
];
다음으로 그룹화되는 새로운 자동차 객체 배열을 만들고 싶습니다 make
.
var cars = {
'audi': [
{
'model': 'r8',
'year': '2012'
}, {
'model': 'rs5',
'year': '2013'
},
],
'ford': [
{
'model': 'mustang',
'year': '2012'
}, {
'model': 'fusion',
'year': '2015'
}
],
'kia': [
{
'model': 'optima',
'year': '2012'
}
]
}
티모의 대답 은 내가 어떻게 할 것인가입니다. 단순 _.groupBy
하며 그룹화 된 구조의 개체에서 일부 복제를 허용합니다.
그러나 OP는 또한 중복 make
키를 제거 하도록 요청했습니다 . 끝까지 가고 싶다면 :
var grouped = _.mapValues(_.groupBy(cars, 'make'),
clist => clist.map(car => _.omit(car, 'make')));
console.log(grouped);
수율 :
{ audi:
[ { model: 'r8', year: '2012' },
{ model: 'rs5', year: '2013' } ],
ford:
[ { model: 'mustang', year: '2012' },
{ model: 'fusion', year: '2015' } ],
kia: [ { model: 'optima', year: '2012' } ] }
이 사용 Underscore.js, 메모를하고 싶어하는 경우 해당 버전의 그 _.mapValues
라고 _.mapObject
.
일반 자바 스크립트에서는 Array#reduce
객체와 함께 사용할 수 있습니다.
var cars = [{ make: 'audi', model: 'r8', year: '2012' }, { make: 'audi', model: 'rs5', year: '2013' }, { make: 'ford', model: 'mustang', year: '2012' }, { make: 'ford', model: 'fusion', year: '2015' }, { make: 'kia', model: 'optima', year: '2012' }],
result = cars.reduce(function (r, a) {
r[a.make] = r[a.make] || [];
r[a.make].push(a);
return r;
}, Object.create(null));
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
을 찾고 있습니다 _.groupBy()
.
필요한 경우 개체에서 그룹화하는 속성을 제거하는 것은 간단해야합니다.
var cars = [{'make':'audi','model':'r8','year':'2012'},{'make':'audi','model':'rs5','year':'2013'},{'make':'ford','model':'mustang','year':'2012'},{'make':'ford','model':'fusion','year':'2015'},{'make':'kia','model':'optima','year':'2012'},];
var grouped = _.groupBy(cars, function(car) {
return car.make;
});
console.log(grouped);
<script src='https://cdn.jsdelivr.net/lodash/4.17.2/lodash.min.js'></script>
보너스로 ES6 화살표 함수를 사용하면 더 좋은 구문을 얻을 수 있습니다.
const grouped = _.groupBy(cars, car => car.make);
es6의 특정 키로 객체 배열을 그룹화하는 짧은 버전 :
result = array.reduce((h, obj) => Object.assign(h, { [obj.key]:( h[obj.key] || [] ).concat(obj) }), {})
더 긴 버전 :
result = array.reduce(function(h, obj) {
h[obj.key] = (h[obj.key] || []).concat(obj);
return h;
}, {})
원래 질문은 제조업체별로 자동차를 그룹화하는 방법을 묻는 것처럼 보이지만 각 그룹에서는 제조업체를 생략합니다. 따라서 대답은 다음과 같습니다.
result = cars.reduce((h, {model,year,make}) => {
return Object.assign(h, { [make]:( h[make] || [] ).concat({model,year})})
}, {})
다음은 https://github.com/you-dont-need/You-Dont-Need-Lodash-UnderscoregroupBy
에서 코드를 일반화 한 자체 함수입니다.
function groupBy(xs, f) {
return xs.reduce((r, v, i, a, k = f(v)) => ((r[k] || (r[k] = [])).push(v), r), {});
}
const cars = [{ make: 'audi', model: 'r8', year: '2012' }, { make: 'audi', model: 'rs5', year: '2013' }, { make: 'ford', model: 'mustang', year: '2012' }, { make: 'ford', model: 'fusion', year: '2015' }, { make: 'kia', model: 'optima', year: '2012' }];
const result = groupBy(cars, (c) => c.make);
console.log(result);
_.groupBy func에 의해 반복마다 호출되는 함수 내에서 객체를 수정할 수 있습니다. 소스 배열은 그의 요소를 변경합니다!
var res = _.groupBy(cars,(car)=>{
const makeValue=car.make;
delete car.make;
return makeValue;
})
console.log(res);
console.log(cars);
var cars = [{
make: 'audi',
model: 'r8',
year: '2012'
}, {
make: 'audi',
model: 'rs5',
year: '2013'
}, {
make: 'ford',
model: 'mustang',
year: '2012'
}, {
make: 'ford',
model: 'fusion',
year: '2015'
}, {
make: 'kia',
model: 'optima',
year: '2012'
}].reduce((r, a) => {
const {
model,
year,
make
} = a;
r[make] = [...r[make] || [], {
model,
year
}];
return r;
}, {});
console.log(cars);
간단한 for
루프로 도 가능 합니다.
const result = {};
for(const {make, model, year} of cars) {
if(!result[make]) result[make] = [];
result[make].push({ model, year });
}
나는 떠날거야 REAL GROUP BY
정확히 같은 JS 배열 예를 들어이 작업을 여기에
const inputArray = [
{ Phase: "Phase 1", Step: "Step 1", Task: "Task 1", Value: "5" },
{ Phase: "Phase 1", Step: "Step 1", Task: "Task 2", Value: "10" },
{ Phase: "Phase 1", Step: "Step 2", Task: "Task 1", Value: "15" },
{ Phase: "Phase 1", Step: "Step 2", Task: "Task 2", Value: "20" },
{ Phase: "Phase 2", Step: "Step 1", Task: "Task 1", Value: "25" },
{ Phase: "Phase 2", Step: "Step 1", Task: "Task 2", Value: "30" },
{ Phase: "Phase 2", Step: "Step 2", Task: "Task 1", Value: "35" },
{ Phase: "Phase 2", Step: "Step 2", Task: "Task 2", Value: "40" }
];
var outObject = inputArray.reduce(function(a, e) {
// GROUP BY estimated key (estKey), well, may be a just plain key
// a -- Accumulator result object
// e -- sequentally checked Element, the Element that is tested just at this itaration
// new grouping name may be calculated, but must be based on real value of real field
let estKey = (e['Phase']);
(a[estKey] ? a[estKey] : (a[estKey] = null || [])).push(e);
return a;
}, {});
console.log(outObject);
Да здравствуют высокие показатели мастерства программистов во имя процветания всего человечества! Ура, товарищи!
재사용 할 수있는 방법 생성
Array.prototype.groupBy = function(prop) {
return this.reduce(function(groups, item) {
const val = item[prop]
groups[val] = groups[val] || []
groups[val].push(item)
return groups
}, {})
};
그런 다음 아래에서 모든 기준으로 그룹화 할 수 있습니다.
const groupByMake = cars.groupBy('make');
console.log(groupByMake);
var cars = [
{
'make': 'audi',
'model': 'r8',
'year': '2012'
}, {
'make': 'audi',
'model': 'rs5',
'year': '2013'
}, {
'make': 'ford',
'model': 'mustang',
'year': '2012'
}, {
'make': 'ford',
'model': 'fusion',
'year': '2015'
}, {
'make': 'kia',
'model': 'optima',
'year': '2012'
},
];
//re-usable method
Array.prototype.groupBy = function(prop) {
return this.reduce(function(groups, item) {
const val = item[prop]
groups[val] = groups[val] || []
groups[val].push(item)
return groups
}, {})
};
// initiate your groupBy. Notice the recordset Cars and the field Make....
const groupByMake = cars.groupBy('make');
console.log(groupByMake);
//At this point we have objects. You can use Object.keys to return an array
키가 null 일 수 있고 다른 것으로 그룹화하려는 경우
var cars = [{'make':'audi','model':'r8','year':'2012'},{'make':'audi','model':'rs5','year':'2013'},{'make':'ford','model':'mustang','year':'2012'},{'make':'ford','model':'fusion','year':'2015'},{'make':'kia','model':'optima','year':'2012'},
{'make':'kia','model':'optima','year':'2033'},
{'make':null,'model':'zen','year':'2012'},
{'make':null,'model':'blue','year':'2017'},
];
result = cars.reduce(function (r, a) {
key = a.make || 'others';
r[key] = r[key] || [];
r[key].push(a);
return r;
}, Object.create(null));
function groupBy(data, property) {
return data.reduce((acc, obj) => {
const key = obj[property];
if (!acc[key]) {
acc[key] = [];
}
acc[key].push(obj);
return acc;
}, {});
}
groupBy(people, 'age');
나를 위해 잘 작동하는 이것을 시도하십시오.
let grouped = _.groupBy(cars, 'make');
다음 array#forEach()
과 같은 방법 을 사용할 수도 있습니다 .
const cars = [{ make: 'audi', model: 'r8', year: '2012' }, { make: 'audi', model: 'rs5', year: '2013' }, { make: 'ford', model: 'mustang', year: '2012' }, { make: 'ford', model: 'fusion', year: '2015' }, { make: 'kia', model: 'optima', year: '2012' }];
let newcars = {}
cars.forEach(car => {
newcars[car.make] ? // check if that array exists or not in newcars object
newcars[car.make].push({model: car.model, year: car.year}) // just push
: (newcars[car.make] = [], newcars[car.make].push({model: car.model, year: car.year})) // create a new array and push
})
console.log(newcars);
@metakunfu 답변이 마음에 들었지만 예상 출력을 정확하게 제공하지 않습니다. 다음은 최종 JSON 페이로드에서 "make"를 제거하는 업데이트입니다.
var cars = [
{
'make': 'audi',
'model': 'r8',
'year': '2012'
}, {
'make': 'audi',
'model': 'rs5',
'year': '2013'
}, {
'make': 'ford',
'model': 'mustang',
'year': '2012'
}, {
'make': 'ford',
'model': 'fusion',
'year': '2015'
}, {
'make': 'kia',
'model': 'optima',
'year': '2012'
},
];
result = cars.reduce((h, car) => Object.assign(h, { [car.make]:( h[car.make] || [] ).concat({model: car.model, year: car.year}) }), {})
console.log(JSON.stringify(result));
산출:
{
"audi":[
{
"model":"r8",
"year":"2012"
},
{
"model":"rs5",
"year":"2013"
}
],
"ford":[
{
"model":"mustang",
"year":"2012"
},
{
"model":"fusion",
"year":"2015"
}
],
"kia":[
{
"model":"optima",
"year":"2012"
}
]
}
lodash / fp를 사용하면 키로 _.flow()
첫 번째 그룹이 있는 함수를 만든 다음 각 그룹을 매핑하고 각 항목에서 키를 생략 할 수 있습니다.
const { flow, groupBy, mapValues, map, omit } = _;
const groupAndOmitBy = key => flow(
groupBy(key),
mapValues(map(omit(key)))
);
const cars = [{ make: 'audi', model: 'r8', year: '2012' }, { make: 'audi', model: 'rs5', year: '2013' }, { make: 'ford', model: 'mustang', year: '2012' }, { make: 'ford', model: 'fusion', year: '2015' }, { make: 'kia', model: 'optima', year: '2012' }];
const groupAndOmitMake = groupAndOmitBy('make');
const result = groupAndOmitMake(cars);
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
<script src='https://cdn.jsdelivr.net/g/lodash@4(lodash.min.js+lodash.fp.min.js)'></script>
모든 필드에 입력하지 않으려면 @Jonas_Wilms 의 답변 을 기반으로 작성하십시오.
var result = {};
for ( let { first_field, ...fields } of your_data )
{
result[first_field] = result[first_field] || [];
result[first_field].push({ ...fields });
}
나는 벤치 마크를 만들지 않았지만 for 루프를 사용하는 것이이 답변 에서 제안 된 것보다 더 효율적이라고 생각 합니다.
const reGroup = (list, key) => {
const newGroup = {};
list.forEach(item => {
const newItem = Object.assign({}, item);
delete newItem[key];
newGroup[item[key]] = newGroup[item[key]] || [];
newGroup[item[key]].push(newItem);
});
return newGroup;
};
const animals = [
{
type: 'dog',
breed: 'puddle'
},
{
type: 'dog',
breed: 'labradoodle'
},
{
type: 'cat',
breed: 'siamese'
},
{
type: 'dog',
breed: 'french bulldog'
},
{
type: 'cat',
breed: 'mud'
}
];
console.log(reGroup(animals, 'type'));
const cars = [
{
'make': 'audi',
'model': 'r8',
'year': '2012'
}, {
'make': 'audi',
'model': 'rs5',
'year': '2013'
}, {
'make': 'ford',
'model': 'mustang',
'year': '2012'
}, {
'make': 'ford',
'model': 'fusion',
'year': '2015'
}, {
'make': 'kia',
'model': 'optima',
'year': '2012'
},
];
console.log(reGroup(cars, 'make'));
ES6를 사용하는 프로토 타입 버전도 있습니다. 기본적으로 이것은 감소 함수를 사용하여 누산기 및 현재 항목을 전달한 다음이를 사용하여 전달 된 키를 기반으로 "그룹화 된"배열을 빌드합니다. 감소의 내부 부분은 복잡해 보일 수 있지만 본질적으로 전달 된 객체의 키가 존재하는지 확인하고 빈 배열을 생성하지 않으면 현재 항목을 새로 생성 된 배열에 추가합니다. 그렇지 않으면 스프레드를 사용합니다. 연산자는 현재 키 배열의 모든 객체를 전달하고 현재 항목을 추가합니다. 이것이 누군가를 돕기를 바랍니다!.
Array.prototype.groupBy = function(k) {
return this.reduce((acc, item) => ((acc[item[k]] = [...(acc[item[k]] || []), item]), acc),{});
};
const projs = [
{
project: "A",
timeTake: 2,
desc: "this is a description"
},
{
project: "B",
timeTake: 4,
desc: "this is a description"
},
{
project: "A",
timeTake: 12,
desc: "this is a description"
},
{
project: "B",
timeTake: 45,
desc: "this is a description"
}
];
console.log(projs.groupBy("project"));
참고 URL : https://stackoverflow.com/questions/40774697/how-to-group-an-array-of-objects-by-key
'developer tip' 카테고리의 다른 글
프로덕션 애플리케이션에 Coffeescript를 사용한 사람이 있습니까? (0) | 2020.08.30 |
---|---|
함수형 프로그래밍-불변성은 비용이 많이 듭니까? (0) | 2020.08.30 |
파이썬 첫 번째와 마지막 큰 따옴표를 어떻게 제거 할 수 있습니까? (0) | 2020.08.29 |
Swift에서 메일 앱을 여는 방법 (0) | 2020.08.29 |
클래스 이름으로 요소를 제거 하시겠습니까? (0) | 2020.08.29 |