[英]How to sort array of objects by value of different keys in JavaScript?
我有一個包含 user_id、score、time_taken 等的數組。
我想設置類似數組的每個用戶分數將被添加到唯一用戶的唯一數組中,並將按他的分數和 time_taken 值排序。
這是我的代碼
let data = [
{ "user_id": "8-a-1", "course_id": 802, "score": 10, "time_taken": 284000 },
{ "user_id": "8-a-1", "course_id": 802, "score": 10, "time_taken": 284000 },
{ "user_id": "8-a-1", "course_id": 802, "score": 10, "time_taken": 284000 },
{ "user_id": "8-a-1", "course_id": 803, "score": 10, "time_taken": 284000 },
{ "user_id": "5-a-1", "course_id": 502, "score": 10, "time_taken": 284000 },
{ "user_id": "5-a-2", "course_id": 502, "score": 10, "time_taken": 284000 },
{ "user_id": "5-a-1", "course_id": 503, "score": 10, "time_taken": 296000 },
{ "user_id": "5-a-1", "course_id": 502, "score": 0, "time_taken": 293000 },
{ "user_id": "5-a-1", "course_id": 503, "score": 0, "time_taken": 299000 },
{ "user_id": "5-a-1", "course_id": 502, "score": 30, "time_taken": 287000 },
{ "user_id": "5-a-1", "course_id": 503, "score": 0, "time_taken": 299000 },
{ "user_id": "5-a-1", "course_id": 504, "score": 20, "time_taken": 299000 },
{ "user_id": "5-a-1", "course_id": 504, "score": 10, "time_taken": 299000 },
{ "user_id": "5-a-1", "course_id": 503, "score": 0, "time_taken": 299000 },
{ "user_id": "5-a-1", "course_id": 503, "score": 0, "time_taken": 299000 },
{ "user_id": "5-a-1", "course_id": 503, "score": 0, "time_taken": 299000 },
{ "user_id": "5-a-1", "course_id": 503, "score": 0, "time_taken": 299000 },
{ "user_id": "5-a-1", "course_id": 503, "score": 0, "time_taken": 299000 },
{ "user_id": "5-a-1", "course_id": 503, "score": 0, "time_taken": 299000 },
{ "user_id": "5-a-1", "course_id": 503, "score": 0, "time_taken": 299000 },
{ "user_id": "5-a-1", "course_id": 503, "score": 0, "time_taken": 299000 },
{ "user_id": "5-a-1", "course_id": 503, "score": 0, "time_taken": 299000 },
]
我試圖減少數組
data = data.reduce((c, i) => {
c[i.user_id] = (c[i.user_id] || 0) + parseFloat(i.score)
return c
}, {});
我想要這樣的結果
[
{user_id: "5-a-1", score: 80, time_taken: "total time taken will be count"},
{user_id: "5-a-2", score: 30, time_taken: "total time taken will be count"},
{user_id: "8-a-1", score: 10, time_taken: "total time taken will be count"},
]
let data = [ { "user_id": "8-a-1", "course_id": 802, "score": 10, "time_taken": 284000 }, { "user_id": "8-a-1", "course_id": 802, "score": 10, "time_taken": 284000 }, { "user_id": "8-a-1", "course_id": 802, "score": 10, "time_taken": 284000 }, { "user_id": "8-a-1", "course_id": 803, "score": 10, "time_taken": 284000 }, { "user_id": "5-a-1", "course_id": 502, "score": 10, "time_taken": 284000 }, { "user_id": "5-a-2", "course_id": 502, "score": 10, "time_taken": 284000 }, { "user_id": "5-a-1", "course_id": 503, "score": 10, "time_taken": 296000 }, { "user_id": "5-a-1", "course_id": 502, "score": 0, "time_taken": 293000 }, { "user_id": "5-a-1", "course_id": 503, "score": 0, "time_taken": 299000 }, { "user_id": "5-a-1", "course_id": 502, "score": 30, "time_taken": 287000 }, { "user_id": "5-a-1", "course_id": 503, "score": 0, "time_taken": 299000 }, { "user_id": "5-a-1", "course_id": 504, "score": 20, "time_taken": 299000 }, { "user_id": "5-a-1", "course_id": 504, "score": 10, "time_taken": 299000 }, { "user_id": "5-a-1", "course_id": 503, "score": 0, "time_taken": 299000 }, { "user_id": "5-a-1", "course_id": 503, "score": 0, "time_taken": 299000 }, { "user_id": "5-a-1", "course_id": 503, "score": 0, "time_taken": 299000 }, { "user_id": "5-a-1", "course_id": 503, "score": 0, "time_taken": 299000 }, { "user_id": "5-a-1", "course_id": 503, "score": 0, "time_taken": 299000 }, { "user_id": "5-a-1", "course_id": 503, "score": 0, "time_taken": 299000 }, { "user_id": "5-a-1", "course_id": 503, "score": 0, "time_taken": 299000 }, { "user_id": "5-a-1", "course_id": 503, "score": 0, "time_taken": 299000 }, { "user_id": "5-a-1", "course_id": 503, "score": 0, "time_taken": 299000 }, ] const result = data.reduce((prev, elem)=>{ if(prev[elem.user_id]){ prev[elem.user_id] = { ...prev[elem.user_id], score: prev[elem.user_id].score + elem.score, time_taken: prev[elem.user_id].time_taken + elem.time_taken } }else{ prev[elem.user_id] = elem } return prev; },{}) let ar = [] for(let key in result){ ar.push(result[key]) } const finalResult = ar.sort((a,b)=>b.score-a.score) console.log(finalResult)
這不僅僅是排序,而且可能是一個reduce
、 map
和sort
的序列:
let data = [ { "user_id": "8-a-1", "course_id": 802, "score": 10, "time_taken": 284000 }, { "user_id": "8-a-1", "course_id": 802, "score": 10, "time_taken": 284000 }, { "user_id": "8-a-1", "course_id": 802, "score": 10, "time_taken": 284000 }, { "user_id": "8-a-1", "course_id": 803, "score": 10, "time_taken": 284000 }, { "user_id": "5-a-1", "course_id": 502, "score": 10, "time_taken": 284000 }, { "user_id": "5-a-2", "course_id": 502, "score": 10, "time_taken": 284000 }, { "user_id": "5-a-1", "course_id": 503, "score": 10, "time_taken": 296000 }, { "user_id": "5-a-1", "course_id": 502, "score": 0, "time_taken": 293000 }, { "user_id": "5-a-1", "course_id": 503, "score": 0, "time_taken": 299000 }, { "user_id": "5-a-1", "course_id": 502, "score": 30, "time_taken": 287000 }, { "user_id": "5-a-1", "course_id": 503, "score": 0, "time_taken": 299000 }, { "user_id": "5-a-1", "course_id": 504, "score": 20, "time_taken": 299000 }, { "user_id": "5-a-1", "course_id": 504, "score": 10, "time_taken": 299000 }, { "user_id": "5-a-1", "course_id": 503, "score": 0, "time_taken": 299000 }, { "user_id": "5-a-1", "course_id": 503, "score": 0, "time_taken": 299000 }, { "user_id": "5-a-1", "course_id": 503, "score": 0, "time_taken": 299000 }, { "user_id": "5-a-1", "course_id": 503, "score": 0, "time_taken": 299000 }, { "user_id": "5-a-1", "course_id": 503, "score": 0, "time_taken": 299000 }, { "user_id": "5-a-1", "course_id": 503, "score": 0, "time_taken": 299000 }, { "user_id": "5-a-1", "course_id": 503, "score": 0, "time_taken": 299000 }, { "user_id": "5-a-1", "course_id": 503, "score": 0, "time_taken": 299000 }, { "user_id": "5-a-1", "course_id": 503, "score": 0, "time_taken": 299000 }, ]; let red=data.reduce((acc,cur)=>{ let usr=acc[cur.user_id] || (acc[cur.user_id]={score:0,time:0}); usr.score+=cur.score; usr.time+=cur.time_taken; return acc; },{}); console.log("Reduced to an object with 3 keys"); console.log(red); let result=Object.keys(red).map(key=>{ let usr=red[key]; return { user_id:key, score:usr.score, time:usr.time } }); console.log("Mapped to an array"); console.log(result); result.sort((a,b)=>a.user_id.localeCompare(b.user_id)); console.log("Sorted by user_id"); console.log(result);
我會使用lodash
因為它可以輕松分組並生成更具可讀性的代碼。 使用您的data
數組:
import _ from 'lodash';
const data = [...]; // As given in the question
// This will form a new row as the initial accumulator for reducing a group
function newRow(key) {
return { user_id: key, score: 0, time_taken: 0 };
}
// reduce iterator that adds the values of a row to the accumulated values
function addRow(result, row, key) {
return {
...result,
score: result.score + row.score,
time_taken: result.time_taken + row.time_taken,
};
}
// reduce a group of rows
function reduceRows(group, key) {
return _.reduce(group, addRow, newRow(key));
}
// group the data by user_id
let res = _.groupBy(data, "user_id");
// convert into array, one entry per group
// each group gets reduced to a single row
res = _.map(res, reduceRows);
// since groupBy initially returns object that may not be sorted, sort it now
res = _.sortBy(res, "user_id");
見REPL
或者,如果您使用 FP,使用 lodash 的 FP 版本允許您進行組合:
import _ from 'lodash/fp';
// Make map expose key, see: https://github.com/lodash/lodash/issues/1781
const map = _.map.convert({ 'cap': false });
const data = [...]; // As given in the question
const newRow = key => ({ user_id: key, score: 0, time_taken: 0 });
const addRow = (result, row, key) => ({
...result,
score: result.score + row.score,
time_taken: result.time_taken + row.time_taken,
});
const reduceRows = (group, key) => _.reduce(addRow, newRow(key), group);
const res = _.compose(
_.sortBy("user_id"),
map(reduceRows),
_.groupBy("user_id"),
)(data);
見REPL
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.