DEV Community

Adam Crockett 🌀
Adam Crockett 🌀

Posted on

How to Decimate an Array.

An interesting use case arrived yesterday, I loved the simplicity of the code so I thought I'd share it.

Code: boom 💣

export function decimateArray(arr, passes = 1, fidelity = 2) {
  let tmpArr = arr.filter((_, index) => index % fidelity === 0);
  passes--;
  if (passes) {
    tmpArr = decimateArray(tmpArr, passes, fidelity);
  }
  return tmpArr;
}

Enter fullscreen mode Exit fullscreen mode

Use case:

"I have a large array of xy coordinates, I need it to draw freehand on canvas but it's too much data to work with quickly, I just want to draw an approximate polygon. I want the array to be smaller so I can more efficiently loop through the data and I dont care about all of the data just the start and end."

How?

An array is fed in, if the index of the data is modulus of a passed in fidelity then keep this data, also recursively run this dataset through itself by a given number of passes.

In english please?

Large array goes in, smaller array with less detail comes out.

Top comments (4)

Collapse
 
tiagojpdias profile image
Tiago Dias • Edited

I would suggest 4 improvements (3 minor and 1 critical)

Critical bug

1) Provide the fidelity parameter as argument to the function, otherwise will only have a value other than 2 in the first step of the recursion;

Minor suggestions

1) Reduce LOC by decreasing by one in the if statement;
2) Remove obsolete else branch;
3) No need to reassign the variable, just return the result right away;

function decimateArray(arr, passes = 1, fidelity = 2) {
    const filteredArray = arr.filter((_, index) => index % fidelity === 0);

    if (--passes) {
        return decimateArray(filteredArray, passes, fidelity);
    }

    return filteredArray;
}

const parameters = [
    Array.from({ length: 100 }, (_, i) => i + 1),
    2,
    4,
];

const decimatedArray = decimateArray(...parameters);

console.log({ decimatedArray }); // { decimatedArray: [ 1, 17, 33, 49, 65, 81, 97 ] }

BTW sorry if I sound picky...

Collapse
 
adam_cyclones profile image
Adam Crockett 🌀

Array from with a function callback isn't as fast as mapping an empty array from an Array constructor. 🤣

It's not the point that it's buggy, it's important that you can take my crappy code and make something better, success. Still the failure to pass args recursively is something il fix.

Collapse
 
mattthecuber profile image
MattTheCuber

A good way to implement this if you already know the approximate length you want your array is:
while (arr.length > 30) arr = decimateArray(arr);

Collapse
 
adam_cyclones profile image
Adam Crockett 🌀

Nice catch I like this 😌