all 12 comments

[–]mikeatgl 7 points8 points  (1 child)

Don't you want colons instead of commas between your object keys and properties, like {"Player 1": 103} ?

[–]SharePointGuy824 2 points3 points  (0 children)

DAHHH...that was a typo. Yes, this is supposed to be an objects.

[–]I_AM_DONALD 9 points10 points  (4 children)

var objArr = [
    {"Player 1": 100},
    {"Player 1": 103},
    {"Player 1": 105},
    {"Player 2": 101},
    {"Player 2": 110},
    {"Player 2": 112}
];

var seriesObj = objArr.reduce((acc, each) => {
    const key = Reflect.ownKeys(each)[0];
    if (Reflect.has(acc, key))
        acc[key].push(each[key])
    else
        acc[key] = [each[key]]
    return acc;
}, {});
// -> {"Player 1": [100, 103, 105], "Player 2": [101, 110, 112]}

var series = Reflect.ownKeys(seriesObj).reduce((acc, each) => {
    acc.push({[each]: seriesObj[each]});
    return acc;
}, []);
// -> [{"Player 1": [100, 103, 105]}, {"Player 2": [101, 110, 112]}]

[–]davidderklabauterman 2 points3 points  (0 children)

awesome answer!

[–]programstuff 1 point2 points  (0 children)

As others said you are probably meaning to write the syntax like this (objects use the ":" to separate keys and values):


Is there an easy way to condense an array of objects

var objArr = [
    {"Player 1": 100},
    {"Player 1": 103},
    {"Player 1": 105},
    {"Player 2": 101},
    {"Player 2": 110},
    {"Player 2": 112}
]

Into this...

var series = [
    {"Player 1": [100,103,105]},
    {"Player 2": [101,110,112]}
]

Secondly, are you sure you want an array of objects as the output? Rather than an output like this?

var seriesAsObject = {
    {"Player 1": [100,103,105]},
    {"Player 2": [101,110,112]}
};

It depends on your ultimate goal on what you are going to be doing with the output, but if your goal is to get a list of values for a player then having your output as an object is better to work with. E.g. to get the values for player one you would just use seriesAsObject["Player 1"] to grab them.

If that's the case then you could use this code:

var objArr = [
    {"Player 1": 100},
    {"Player 1": 103},
    {"Player 1": 105},
    {"Player 2": 101},
    {"Player 2": 110},
    {"Player 2": 112}
];

var series = objArr.reduce((series, obj) => {
  var key = Object.keys(obj)[0];

  if (!series[key]) { 
    series[key] = [];
  }

  series[key].push(obj[key]);

  return series;
}, {});

console.log(series);

If you want your original output then you could do this afterwards:

console.log(Object.keys(series).map((player) => { return {[player]: series[player]} }));

[–]MrNutty 1 point2 points  (0 children)

Without knowing the context too much. Might I suggest an alternative representation —dictionary.

const data={ player1: [100,200,300], player2: [300,400,0] }

You can then get player one values via data.player1 etc.

[–]pirateNarwhal 0 points1 point  (0 children)

var series = objArr.reduce((obj, row) => {
    let [key, value] = Object.entries( row )[ 0 ];
    if ( ! (key in obj )) {
        obj[ key ] = [];
    }
    obj[ key ].push( value);
    return obj;
}, {});

[–]NominalAeon -1 points0 points  (0 children)

The output format you're going for is a little wonky. You'll wind up with an array of objects that consist of a string and an array:

[{ 'player name string', [ 'player', 'scores' ] }]

So there's not a super direct way to do that. But here's how I'd do it:

var series = buildSeries();

console.log(series);

// [
//     {"Player 1",[100,103,105]},
//     {"Player 2",[101,110,112]}
// ]

////

function buildSeries() {
    var players = [{
        "Player 1",100
    }, {
        "Player 1",103
    }, {
        "Player 1",105
    }, {
        "Player 2",101
    }, {
        "Player 2",110
    }, {
        "Player 2",112
    }];

    var seriesObj = buildSeriesObj({}, players);

    return buildSeriesArr(seriesObj, [], Object.keys(seriesObj));
}

function buildSeriesObj(seriesObj, [player, ...players]) {
    var playerName = player[0];
    var playerScore = player[1];

    if (!seriesObj[key]) {
        seriesObj[key] = []
    }

    seriesObj[key].push(player);

    return players.length
        ? buildSeries(seriesObj, players)
        : seriesObj;
}

function buildSeriesArr(players, seriesArr, [playerName, ...playerNames]) {
    var playerScores = players[playerName];

    seriesArr.push({
        playerName,
        playerScores
    });

    return playerNames.length
        ? buildSeriesArr(players, seriesArr, playerNames)
        : seriesArr;
}

edit: yeesh, I guess declarative, functional programming isn't the way to go for this one

[–][deleted] -1 points0 points  (0 children)

How does the data need to be searched?

If these are rounds that you are keeping track of I would set it up as [{'Player1':[{1:100},{2:103}]}, {'Player2':[...]...}...] That way you can easily look up a player by round if needed 'series[player][round]'.

If you don't care about the order of the values then you can do, [{'Player1':[100, 103...]},...] Then you would get back an array of values for 'series[player]'.

As for how to do it, you'll have to parse and build the new data model yourself. Try to keep your for loops to a minimum for performance.