0

I have a number that is divisible by 4, e.g. 20. Now I need to create a string that looks as follows:

(1, 2, 3, 4), (5, 6, 7, 8), (9, 10, 11, 12), (13, 14, 15, 16), (17, 18, 19, 20)

So, all the numbers from 1 to 20, grouped in packages of 4, wrapped in parentheses, and everything separated by commas.

My current approach looks like this:

const placeholders = [];

for (let i = 0; i < events.length; i++) {
  const base = i * 4 + 1;

  placeholders.push(`(${base}, ${base + 1}, ${base + 2}, ${base + 3})`);
}

const result = placeholders.join(',');

Is there a way to do this a) more efficiently, and b) in a more readable way?

Golo Roden
  • 140,679
  • 96
  • 298
  • 425

2 Answers2

3
var results = [];
for(var i = 1; i <= events.length * 4; i++){
  var m = i % 4;
  results.push((m==1 ? "(" : "") + i + (m==0 ? ")" : ""));
}
results = results.join(", ");

More readable? Probably not. More efficient? They run about the same.

The best take-away is probably that you could change your loop such that it starts at 1.

Ouroborus
  • 16,237
  • 4
  • 39
  • 62
  • +1 for the smart way of doing of figuring out the `(` and `)` concatenation with the ternary operators. I deleted my answer because yours is better. However it would be cool if you would take `4` as an argument to a function producing this string - I realise that isn't a requirement of the OP question :) – Robin Mackenzie Dec 10 '16 at 13:26
  • Also, why not have a go at this one: http://stackoverflow.com/questions/41075559/how-to-efficiently-build-this-array ;) – Robin Mackenzie Dec 10 '16 at 13:28
  • @RobinMackenzie I would've gone with [this strategy](http://stackoverflow.com/a/41075610/367865) but that answer did a better job than I would've. – Ouroborus Dec 10 '16 at 13:37
  • Any idea *why* its faster? Make a reasonable guess. If not, state in which environment you benchmarked the solutions against each other, as it might easily change with new version or be different elsewhere. – Bergi Dec 10 '16 at 14:55
  • @Bergi I suspect it's because I'm using concatenation rather than template literals. Template literals require scanning through the string, breaking it up, and reassembling with the variable values in place. While that's done as part of the javascript engine, templating is still pretty complex, relatively. – Ouroborus Dec 10 '16 at 21:24
  • Nah, that's only done once at the parsing stage, the execution is exactly equivalent to `placeholders.push('('+(base)+', '+(base + 1)+', '+(base + 2)+', '+(base + 3)+')');`. – Bergi Dec 10 '16 at 22:04
  • @Bergi Are you sure? I don't see any other significant differences. I suspect the specific problem is that we don't have all the possible optimizations for template literals in place yet in the engine. http://stackoverflow.com/q/29055518/367865 – Ouroborus Dec 10 '16 at 23:07
  • @Ouroborus the accepted answer has aged fast in one and a half years :-) See the updates on that thread stating that FF 50 or Node 6 show no difference any more. – Bergi Dec 10 '16 at 23:08
  • @Bergi I am at a loss then. I don't see any other significant difference in the code. Measurements show that Chrome runs my code about twice as fast and Firefox runs it about four times as fast. – Ouroborus Dec 10 '16 at 23:19
  • 2
    Uh, your conditional prepending/appending of the parenthesis is a very different approach, so there might indeed be benefits. E.g. the array becomes larger, with smaller elements, so maybe the string buffer is faster with that. – Bergi Dec 10 '16 at 23:23
  • @Bergi I guess that does count as a significant difference. Though I would've thought my approach would be less performant in that aspect given that it makes checks on every integer while OPs code essentially unrolls that. – Ouroborus Dec 10 '16 at 23:27
  • 1
    @Bergi Turns out it's probably an error in my code. Both use `events.length` but I assumed it was `20` while it's actually `5`. This error means that in testing OP's code would iterate four times as much. – Ouroborus Dec 10 '16 at 23:42
0

Just tried. Don't know efficient or not.

res = '(';
for (i = 1; i <= 20; i++) {
    var mod = i % 4;
    (mod == 1 && i != 1) ? res += ',(' : '';
    res += i;
    res += (mod != 0) ? ',' : ')';
}
saravanabawa
  • 1,607
  • 1
  • 16
  • 23