-1

I've really been wrecking my brain over this one so any assistance is greatly appreciated. I currently have an array of objects and each of these objects has two properties, a timestamp (ms since epoch) and an arbitrary for that timestamp. Like so:

[
    [1518739200000, 1], 
    [1518739200000, 1],
    [1518739200000, 12],
    [1518739200000, 16],
    [1518739200000, 16],
    [1518825600000, 16],
    [1518825600000, 20],
    [1518825600000, 20],
    [1518825600000, 8],
]

What I'm trying to do is to condense the multidimensional array into another multidimensional array which has only the unique values of the first index, the timestamp, and an aggregate count as the second value. In example, I'm looking for this from the given set of data included above.

[
    [1518739200000, 46],
    [1518825600000, 64],
]

I've tried using .reduce in a few ways but haven't had any success yet for this particular kind manipulation.

6
  • Show your attempt, please! Commented May 8, 2018 at 18:59
  • Possible duplicate of Javascript : How group and sum values from multidimensional array Commented May 8, 2018 at 19:00
  • Taking a look now PM77-1 Commented May 8, 2018 at 19:04
  • I don't see how the example works... the sum for the shortest timestamp isn't 32 as far as I can see... Commented May 8, 2018 at 19:05
  • The duplicate is a bit dated. Probably easier to reduce and Map. Commented May 8, 2018 at 19:11

3 Answers 3

1

An alternative using the function reduce

let array = [[1518739200000, 1], [1518739200000, 1],[1518739200000, 12],[1518739200000, 16],[1518739200000, 16],[1518825600000, 16],[1518825600000, 20],[1518825600000, 20],[1518825600000, 8]];
let result = Object.values(array.reduce((a, [key, value]) => {
  (a[key] || (a[key] = [key, 0]))[1] += value;
  return a;
}, {}));

console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }

Sign up to request clarification or add additional context in comments.

3 Comments

Very cool stuff, I'd love to be able to right js as succinct as this. Would you mind explaining how (x = [1,2])[1] += 1 works, but (x = 1) += 1 doesn't. Thanks! +1
Interesting, can you explain why you use Object.values & the empty object at the end. I assume thats the initial value though I see we get back a multidimensional array (as requested) so what is the empty object there to do? Thanks!
The idea is to generate an object with the key as the common times and the value as the running total. On each iteration, either the number is added to the total of that key if it already exists or it creates a new key for that time with the running total as 0 and then immediately adds the current number. The whole reduce call would return an object with 2d arrays as values, but if passed into Object.values, you just get an array of the values.
0

You could reduce the array to a Map and use the Map to create an array of arrays using Array.from.

var data = [
  [1518739200000, 1], 
  [1518739200000, 1],
  [1518739200000, 12],
  [1518739200000, 16],
  [1518739200000, 16],
  [1518825600000, 16],
  [1518825600000, 20],
  [1518825600000, 20],
  [1518825600000, 8],
];

console.log(
  Array.from(
    data.reduce(
      (result,[current,num])=>
        result.set(
          current,
          (result.get(current)||0)+num
        ),
      new Map()
    )
  )
)

Comments

0

Use reduce

var x = [
        [1518739200000, 1], 
        [1518739200000, 1],
        [1518739200000, 12],
        [1518739200000, 16],
        [1518739200000, 16],
        [1518825600000, 16],
        [1518825600000, 20],
        [1518825600000, 20],
        [1518825600000, 8],
    ]

x.reduce(function(ac,d,i,a){if(!ac.some(function(dd,ii){return dd[0] === d[0] && dd[1] === d[1]})){ac.push(d)
}return ac},[]);

The above gets unique values for BOTH indexes, for the first one only:

x.reduce(function(ac,d,i,a){if(!ac.some(function(dd,ii){return dd[0] === d[0]})){ac.push(d)}return ac},[])

But then, the question is, this gets the first encountered entry, do you have any preference for the second?

UPDATE:Oww, I didn't see the aggreate, this is for it:

x.reduce(function(ac,d,i,a){
    var index;
    if(
        !ac.some(function(dd,ii){
            return dd[0] === d[0] ? (index=ii,true) : false
        })
    ){
        ac.push(d.slice())
    } else {
        ac[index][1] += d[1];
    }
    return ac
},[])

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.