如何使用 reduce 創建一個函式,該函式將接收物件陣列并回傳具有唯一鍵的物件目錄,但允許重復值?
- 每個鍵都是人的名字
- 每個重復的鍵都有一個帶有數字目錄的嵌套陣列
- 如果沒有重復的鍵,則該鍵應僅包含一個物件
我希望輸出看起來像這樣:
{
Bob: {
'0': { name: 'Bob', age: 30, voted: true },
'1': { name: 'Bob', age: 31, voted: true },
'2': { name: 'Bob', age: 32, voted: true },
},
Jake: {
'0': { name: 'Jake', age: 20, voted: false },
'1': { name: 'Jake', age: 32, voted: true }
},
Phil: { name: 'Phil', age: 21, voted: true },
Ed: { name: 'Ed', age: 55, voted: true },
Tami: { name: 'Tami', age: 54, voted: true },
Mary: { name: 'Mary', age: 31, voted: false },
Becky: { name: 'Becky', age: 43, voted: false },
Joey: { name: 'Joey', age: 41, voted: true },
Jeff: { name: 'Jeff', age: 30, voted: true },
Zack: { name: 'Zack', age: 19, voted: false }
}
這是我的代碼,如果出現兩個重復的名稱,結果會互相吃掉,并且它將第一個物件傳播到鍵中而不添加數字鍵。
let count = 0
const toNamedObj = (arr) => {
return arr.reduce((acc, cur) => {
let key = Object.values(cur)[0]
if(acc.hasOwnProperty(key)){
count
console.log(count)
return {[key]: {...acc[key], [count]: cur} }
}
return {...acc, [key]: cur}
} ,{})
}
const voters = [
{name:'Bob' , age: 30, voted: true},
{name:'Bob' , age: 31, voted: true},
{name:'Bob' , age: 32, voted: true},
{name:'Jake' , age: 32, voted: true},
{name:'Kate' , age: 25, voted: false},
{name:'Jake' , age: 20, voted: false},
{name:'Phil' , age: 21, voted: true},
{name:'Ed' , age:55, voted:true},
{name:'Tami' , age: 54, voted:true},
{name: 'Mary', age: 31, voted: false},
{name: 'Becky', age: 43, voted: false},
{name: 'Joey', age: 41, voted: true},
{name: 'Jeff', age: 30, voted: true},
{name: 'Zack', age: 19, voted: false}
];
console.log(toNamedObj(voters));
uj5u.com熱心網友回復:
使用您當前的方法,您必須能夠在迭代時檢測名稱是否已經存在,嵌套在其中的物件是否是普通選民物件(在這種情況下,必須將其洗掉并替換為類陣列物件),或者如果它是類陣列物件。雖然這是可能的,但它會很復雜。更好的方法是無條件地分組為按名稱索引的陣列,然后將每個陣列轉換為單個投票者物件,或{0: .. 1: }之后轉換為物件。
顯示代碼片段
const toNamedObj = (arr) => {
const votersByName = {};
for (const voter of voters) {
votersByName[voter.name] ??= [];
votersByName[voter.name].push(voter);
}
for (const [name, voters] of Object.entries(votersByName)) {
votersByName[name] = voters.length === 1
? voters[0]
: { ...voters };
}
return votersByName;
}
const voters = [
{name:'Bob' , age: 30, voted: true},
{name:'Bob' , age: 31, voted: true},
{name:'Bob' , age: 32, voted: true},
{name:'Jake' , age: 32, voted: true},
{name:'Kate' , age: 25, voted: false},
{name:'Jake' , age: 20, voted: false},
{name:'Phil' , age: 21, voted: true},
{name:'Ed' , age:55, voted:true},
{name:'Tami' , age: 54, voted:true},
{name: 'Mary', age: 31, voted: false},
{name: 'Becky', age: 43, voted: false},
{name: 'Joey', age: 41, voted: true},
{name: 'Jeff', age: 30, voted: true},
{name: 'Zack', age: 19, voted: false}
];
console.log(toNamedObj(voters));
或者通過映射條目
const toNamedObj = (arr) => {
const votersByName = {};
for (const voter of voters) {
votersByName[voter.name] ??= [];
votersByName[voter.name].push(voter);
}
return Object.fromEntries(
Object.entries(votersByName)
.map(([name, voters]) => ([
name,
voters.length === 1 ? voters[0] : { ...voters }
]))
);
}
const voters = [
{name:'Bob' , age: 30, voted: true},
{name:'Bob' , age: 31, voted: true},
{name:'Bob' , age: 32, voted: true},
{name:'Jake' , age: 32, voted: true},
{name:'Kate' , age: 25, voted: false},
{name:'Jake' , age: 20, voted: false},
{name:'Phil' , age: 21, voted: true},
{name:'Ed' , age:55, voted:true},
{name:'Tami' , age: 54, voted:true},
{name: 'Mary', age: 31, voted: false},
{name: 'Becky', age: 43, voted: false},
{name: 'Joey', age: 41, voted: true},
{name: 'Jeff', age: 30, voted: true},
{name: 'Zack', age: 19, voted: false}
];
console.log(toNamedObj(voters));
我建議不要.reduce在每次迭代中累加器的值相同時使用- 普通for回圈更易于撰寫和理解。
uj5u.com熱心網友回復:
下面介紹的是實作預期目標的一種可能方式。
代碼片段
// method to transform arr to desired format
const toNamedObj = arr => (
arr.reduce(
(acc, {name, voted, ...rest}, idx) => (
(acc[name] ??= []).push({ name, voted, ...rest }),
(idx === arr.length - 1 && Object.entries(acc).forEach(
([k, v]) => (acc[k] = (v.length === 1) ? v[0] : {...v})
)),
acc
),
{}
)
);
/* with explanation
// method to transform arr to desired format
const toNamedObj = arr => (
// iterate using ".reduce()"
arr.reduce(
(acc, {name, voted, ...rest}, idx) => {
// if "name" not present in "acc", set it as empty array
acc[name] ??= [];
// push elt into array
acc[name].push({ name, voted, ...rest });
// when iterating over the last item, special processing
if (idx === arr.length - 1) { // processed last elt in arr
// review each value in "acc" and convert to object
Object.entries(acc)
.forEach(([k, v]) => {
if (v.length === 1) { // only one elt in value-array
// place the elt as-is
acc[k] = v[0];
} else { // multiple elts in val-arr
// convert val-arr to object
acc[k] = {...v};
}
});
};
// always return the accumulator "acc" in ".reduce()" callback
return acc;
},
{} // "acc" is set as an empty object initially
)
);
*/
const voters = [
{name:'Bob' , age: 30, voted: true},
{name:'Bob' , age: 31, voted: true},
{name:'Bob' , age: 32, voted: true},
{name:'Jake' , age: 32, voted: true},
{name:'Kate' , age: 25, voted: false},
{name:'Jake' , age: 20, voted: false},
{name:'Phil' , age: 21, voted: true},
{name:'Ed' , age:55, voted:true},
{name:'Tami' , age: 54, voted:true},
{name: 'Mary', age: 31, voted: false},
{name: 'Becky', age: 43, voted: false},
{name: 'Joey', age: 41, voted: true},
{name: 'Jeff', age: 30, voted: true},
{name: 'Zack', age: 19, voted: false}
];
console.log(toNamedObj(voters));
.as-console-wrapper { max-height: 100% !important; top: 0 }
解釋
添加到上述代碼段的行內注釋。
轉載請註明出處,本文鏈接:https://www.uj5u.com/qianduan/483560.html
標籤:javascript 数组 目的 目录 减少
