1

EDIT

To me JSON.stringify is not the solution here, as it is much slower than recursion

    JSON.stringify(fakeData)
        .replace(/,/g, ';')
        .replace(/:(?={)/g, '')
        .replace(/"/g, '')
//Result
Recursion with reduce x 816,321 ops/sec ±7.38% (80 runs sampled)
JSON.stringify x 578,221 ops/sec ±1.72% (92 runs sampled)
Fastest is Recursion with reduce

I am making a css-in-js library, and I need to use recursion to turn object into string like this:

Input:

const fakeData = {
  a: {
    b: 'c',
    d: 'e'
  }
}

Output:

a{b:c;d:e;}

My recursion function:

const buildKeyframe = (obj) => {
    return Object.entries(obj).reduce((acc, [prop, value]) => {
        if (typeof value === 'string') {
            return `${acc}${prop}:${value};`
        }

        return `${prop}:{${buildKeyframe(value)}}`
    }, '')
}

This function works, but I think there is room for improvement(e.g. use TCO, avoid using reduce)... How can I write a better function to recurse this data structure?

6
  • This question might be better suited to codereview.stackexchange.com, but do please read their tour before posting. Commented Jan 13, 2021 at 3:36
  • Sorry for posting it here. Thank you for your comment. Commented Jan 13, 2021 at 3:39
  • How about this JSON.stringify({a: {b: 'c', d: 'e'}}).replaceAll(',', ';') will this work? But you have that semi-colon at the end did not notice that...anyway you can see if this will do for you. Commented Jan 13, 2021 at 3:50
  • 1
    Why not to use JSON.stringify()? Commented Jan 13, 2021 at 3:51
  • Just ran some benchmarks and updated my question. Commented Jan 13, 2021 at 4:19

1 Answer 1

1

This solution is about 50% faster and also works with more than one css property

const buildKeyframe = obj => {
          let result = '';

          for (const key in obj) {
              let value = obj[key];
              if(obj.hasOwnProperty(key)) {
                result += typeof value === 'string' ?
                 `${key}:${value};` :
                 `${key}{${buildKeyframe(value)}}`;
              }
          }

          return result;
    }

const fakeData = {
a: {
    b: 'c',
    d: 'e',
    g: 'b',
},
b: {
    m: 'n'
}
}

console.log(buildKeyframe(fakeData));

Benchmark.js Test results:

for...in x 1,875,280 ops/sec ±0.40% (87 runs sampled)
reduce x 1,272,530 ops/sec ±0.27% (91 runs sampled)
Fastest is for...in
Sign up to request clarification or add additional context in comments.

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.