2

I have an array:

array = [10, 10, 10, 10, 10]

I want to loop through this array so that it gets a "slope" based on an integer. So if the integer is 2 the result would be:

array = [0, 5, 10, 5, 0]

If I had a even bigger array:

bigArray = [50, 50, 50, 50, 50, 50, 50, 50, 50, 50]

then if the integer is still 2 the result would be:

bigArray = [0, 25, 50, 50, 50, 50, 50, 50, 25, 0]

The value of the integer doesn't matter, as long as the array has "smooth" ends to it like shown above. The integer just specifies how many indices are affected.

Sebastian Olsen
  • 10,318
  • 9
  • 46
  • 91

1 Answers1

3

You can simply count at both ends.

function smooth(array, part) {
    var i;
    array = array.slice();
    for (i = 0; i < part; i++) {
        array[i] = array[i] * i / part;
        array[array.length - 1 - i] = array[array.length - 1 - i] * i / part ;
    }
    return array;
}

document.write('<pre>' + JSON.stringify(smooth([10, 10, 10, 10, 10], 2), 0, 4) + '</pre>');
document.write('<pre>' + JSON.stringify(smooth([50, 50, 50, 50, 50, 50, 50, 50, 50, 50], 2), 0, 4) + '</pre>');

One example with sine

function smooth(array, parts) {
    function f(x) {
        // return x; // linear
        return Math.sin(x * Math.PI / 2); // sine
    }

    var i;
    array = array.slice();
    for (i = 0; i < parts; i++) {
        array[i] = f(i / parts) * array[i] | 0;
        array[array.length - 1 - i] = f(i / parts) * array[array.length - 1 - i] | 0;
    }
    return array;
}

document.write('<pre>' + JSON.stringify(smooth([20, 20, 20, 20, 20, 20, 20], 3), 0, 4) + '</pre>');
document.write('<pre>' + JSON.stringify(smooth([50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50], 5), 0, 4) + '</pre>');

Bonus: Dynamic generation of the array with callback for smoothing

function smooth(length, value, parts, fn) {
    fn = fn || function (x) { return x; };
    return Array.apply(null, { length: length }).map(function (_, i) {
        if (i < parts) {
            return value * fn(i / parts) | 0;
        }
        if (i >= length - parts) {
            return value * fn((length - i - 1) / parts) | 0;
        }
        return value;
    });
}

document.write('<pre>' + JSON.stringify(smooth(5, 10, 2), 0, 4) + '</pre>');
document.write('<pre>' + JSON.stringify(smooth(10, 50, 4), 0, 4) + '</pre>');
document.write('<pre>' + JSON.stringify(smooth(5, 10, 2, function f(x) { return Math.sin(x * Math.PI / 2); }), 0, 4) + '</pre>');
document.write('<pre>' + JSON.stringify(smooth(10, 50, 4, function f(x) { return Math.sin(x * Math.PI / 2); }), 0, 4) + '</pre>');

Edit: This code works with formulas from http://easings.net/. For further readings I suggest to visit What is an easing function?.

// formula     http://easings.net/
// description https://stackoverflow.com/questions/8316882/what-is-an-easing-function
// x: percent
// t: current time,
// b: begInnIng value,
// c: change In value,
// d: duration
function easeInOutQuad(x, t, b, c, d) {
    if ((t /= d / 2) < 1) {
        return c / 2 * t * t + b;
    } else {
        return -c / 2 * ((--t) * (t - 2) - 1) + b;
    }
}

function smooth(array, parts) {
    function fn(f, x, v) {
        return f(x, 1000 * x, 0, v, 1000)
    }

    var i;
    array = array.slice();
    for (i = 0; i < parts; i++) {
        array[i] = fn(easeInOutQuad, i / parts, array[i]) | 0;
        array[array.length - 1 - i] = fn(easeInOutQuad, i / parts, array[array.length - 1 - i]) | 0;
    }
    return array;
}

document.write('<pre>' + JSON.stringify(smooth([20, 20, 20, 20, 20, 20, 20], 3), 0, 4) + '</pre>');
document.write('<pre>' + JSON.stringify(smooth([50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50], 4), 0, 4) + '</pre>');
document.write('<pre>' + JSON.stringify(smooth([50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50], 5), 0, 4) + '</pre>');
Community
  • 1
  • 1
Nina Scholz
  • 376,160
  • 25
  • 347
  • 392