3
\$\begingroup\$

I am writing a function to decode data from a run length encoded format like:

 { dataGroup: { count: [4, 4, 2, 1], dataOne: [1, 3, 2, 1], dataTwo: [7, -1, 9, 0], dataThree: [3, 8, 1, 2] } } 

to

{ groupName: { dataOne: [1, 1, 1, 1, 3, 3, 3, 3, 2, 2, 1], dataTwo: [7, 7, 7, 7,-1,-1,-1,-1, 9, 9, 0], dataThree: [3, 3, 3, 3, 8, 8, 8, 8, 1, 1, 2] } } 

I have written two solutions to date but feel like there may yet be a better way.

function decode(obj) { const arrayLengthN = (N, data=null) => [...Array(N)].map(_ => data); const [ group ] = Object.keys(obj); const { count, ...data } = obj[group]; const dataKeys = Object.keys(data); // method one // output object to be written upon iteration over count and data const output = {}; // populate output with empty arrays to push to dataKeys.map(key => output[key] = []); // do the decoding count .map((n, i) => { dataKeys .map(key => { output[key].push(...arrayLengthN(n, data[key][i])); }); }); // method two const otherMethod = { [group]: Object.assign( {}, ...dataKeys.map((key) => { return { [key] : count .map((n, i) => dataKeys .map(key => arrayLengthN(n, data[key][i])) ) .flat(2) }; }) )}; return {[group]: output} // or return otherMethod } 

Is there anything wrong with the first method? It feels clunky to create an object, add empty arrays to it, and then mutate that object from within a .map call. That being said, to me it seems far more readable.

Any help or comments much appreciated.

Cheers,

P

\$\endgroup\$

    2 Answers 2

    1
    \$\begingroup\$

    May i suggest a shorter code?

    var data = { dataGroup: { count: [4, 4, 2, 1], dataOne: [1, 3, 2, 1], dataTwo: [7, -1, 9, 0], dataThree: [3, 8, 1, 2] } } var processedData = Object.keys(data.dataGroup).filter(key => key != 'count').reduce((acc, key) => { acc.groupName[key] = []; data.dataGroup.count.forEach((amount, index) => { for (let i = 0; i < amount; i++) { acc.groupName[key].push(data.dataGroup[key][index]); } }); return acc; }, { groupName: {}}); console.log(processedData);

    \$\endgroup\$
    2
    • \$\begingroup\$Offering an alternate solution isn't really considered giving a good answer, and "Your code is too long" might not really be an insightful observation. Could you discuss why you think the code is too long? Please read codereview.stackexchange.com/help/how-to-answer\$\endgroup\$
      – pacmaninbw
      CommentedJun 6, 2019 at 13:02
    • \$\begingroup\$Hi, thanks for your solution. One thing to point out is that you've fixed the key 'groupName' in your output. For my purposes, the group key must be matched to the input object's group key.\$\endgroup\$
      – Batters
      CommentedJun 6, 2019 at 13:32
    0
    \$\begingroup\$

    A bit late but looks good to me. You could use Array.prototype.fill instead of arrayLengthN, and perhaps a reducer as the function but that’s a matter of taste:

    // assignment as expression to avoid explicit returns set = (obj, key, value) => (obj[key] = value, obj) decode = (output, [group, {count, ...entries}]) => set(output, group, Object.entries(entries).reduce((acc, [key, values]) => set(acc, key, [].concat(...values.map((n, i) => Array(count[i]).fill(n)))) , {})) 

    so you could Object.entries(data).reduce(decode, {}).

    I used concat because in my node version there wasn’t support for flat.

    I like this because all the “variable” names are argument names (although that’s bit of a moot point).

    \$\endgroup\$

      Start asking to get answers

      Find the answer to your question by asking.

      Ask question

      Explore related questions

      See similar questions with these tags.