1

Suppose I need an array with a number of repetitive elements, like this:

[3,3,3,3,3,8,8,8,8,5,5,5,5,5,5] (so that's five 3s, four 8s, and six 5s)

In python, you can define this very elegantly like this:

[3]*5+[8]*4+[5]*6

Are there similar constructions in JS or PHP?

In this example, defining the entire array explicitly isn't that much of a problem. But if there are many elements, with lots of repetitions, this can become very tedious (not to mention prone). I want my code size to stay equal, regardless of whether the array has five 3s or five hundred.

In JS, the shortest I can think of is:

var a = [];
[[3,5],[8,4],[5,6]].forEach(function(x){while(x[1]--)a.push(x[0])});

Similar in PHP:

foreach(array(3=>5,8=>4,5=>6) as $d=>$n) while($n--) $a[]=$d;

Obviously this doesn't score bonus points for readability. Is there a better way (preferably some language construct) to do this?

RocketNuts
  • 9,958
  • 11
  • 47
  • 88

4 Answers4

1

JavaScript

The best way for readability and re-usability is probably to define a function for Array "multiplication", for example this one does it exponentially

function arrMultiply(arr, i) {
    var arr_out = [];
    if (i & 1)
        arr_out = arr_out.concat(arr);
    while ((i >>>= 1) > 0) {
        arr = arr.concat(arr);
        if (i & 1)
            arr_out = arr_out.concat(arr);
    }
    return arr_out;
}

Now you can concat together "multiplied" Arrays

arrMultiply([3], 5).concat(arrMultiply([8], 4)).concat(arrMultiply([5], 6));
// [3, 3, 3, 3, 3, 8, 8, 8, 8, 5, 5, 5, 5, 5, 5]

If you really want to, you can extend the prototype of Array to include the arrMultiply function which would give you syntax closer to what you're already using,

Array.prototype.mul = function (i) {return arrMultiply(this, i);};

[3].mul(5).concat([8].mul(4)).concat([5].mul(6));
// [3, 3, 3, 3, 3, 8, 8, 8, 8, 5, 5, 5, 5, 5, 5]
Paul S.
  • 64,864
  • 9
  • 122
  • 138
  • In this answer I called the operation _"multiplication"_ as we're implementing a behaviour of `*` from _Python_, but re-reading this answer I think it may be better to use the word _repeat_ instead, as _multiply_ can be ambiguous in this context (think _scalar multiplication, dot product, cross product, repetition, etc_) – Paul S. Sep 05 '15 at 10:39
1

In JavaScript:

Array.apply(null, Array(c)).map(function () {
    return v;
});

function f(c, v) {
    return Array.apply(null, Array(c)).map(function () {
        return v;
    });
}

document.write(f(5, 3).concat(f(4, 8)).concat(f(6, 5)));

".apply()" allows to pass arguments to a function in the form of an array, roughly:

say.apply(null, ['hello', 'world'])

Is the same as:

say('hello', 'world')

Hence, since Array(3) gives [undefined x 3]:

Array.apply(null, Array(3))

Is the same as:

Array(undefined, undefined, undefined)

Why is it required? Refer to JavaScript "new Array(n)" and "Array.prototype.map" weirdness.

Community
  • 1
  • 1
Vidul
  • 10,128
  • 2
  • 18
  • 20
0

You can use array_fill() to fill up an array with the values and array_merge() it into your results array, e.g.

<?php

    $arr = [[3,5],[8,4],[5,6]];
    $result = [];
    foreach($arr as $v)
        $result = array_merge($result, array_fill(0, $v[1], $v[0]));

    print_r($result);

?>

output:

Array
(
    [0] => 3
    [1] => 3
    [2] => 3
    [3] => 3
    [4] => 3
    [5] => 8
    [6] => 8
    [7] => 8
    [8] => 8
    [9] => 5
    [10] => 5
    [11] => 5
    [12] => 5
    [13] => 5
    [14] => 5
)
Rizier123
  • 58,877
  • 16
  • 101
  • 156
0

A freaky one (numbers only) x-)

document.write(
  '<pre>' + JSON.stringify(
    makeArray('[1x1,3x4,42x3]')
  ) + '</pre>'
);

function makeArray (expr) {
  return JSON.parse(
    expr.replace(/(\d+)x(\d+)/g, function ($0, $1, $2) {
      return $1 + new Array(+$2).join(','+$1);
    })
  );
}