如何通过JavaScript中不同键的值对对象数组进行排序?

时间:2019-07-14 16:08:42

标签: javascript arrays sorting grouping

我有一个数组,其中包含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"},
]

3 个答案:

答案 0 :(得分:1)

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)

答案 1 :(得分:1)

这不仅是排序,还可能是reducemap然后是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);

答案 2 :(得分:1)

我将使用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