Jacob
Jacob

Reputation: 1395

Lodash swap adjacent items if condition is met

Say I have an array, [1, 2, 3, 4, 5, 3, 4, 6, 3, 7, 4]. I want to swap the values of 3 and 4 iff they are adjacent an in the order [3, 4] (i.e. [4, 3] remain intact). The result of the example would be [1, 2, 4, 3, 5, 4, 3, 6, 3, 7, 4].

Is there an elegant way to do this in Lodash without the use of for loops?

Edit: How about

 _.sortBy(arr, function(value, index) {
    if (value === 3) {
        return index + 0.75;
    } else if (value === 4) {
        return index - 0.75;
    } else {
        return index
    }
});

Edit 2: Went with the following (it's not actually 3 and 4).

return _.reduce(tags, function(out, tag) {
    var word = tag[0];

    if (out[0] && unitPowerSuffixes.hasOwnProperty(word)) {
        out.splice(-1, 0, {
            type: 'unit-power',
            value: unitPowerSuffixes[word]
        }); // Insert one from end
    } else {
        out.push(tag);
    }

    return out;
}, []);

Upvotes: 1

Views: 3048

Answers (2)

Bergi
Bergi

Reputation: 664599

A really functional way would be to use something like splitOn. But we can do that using strings (not even needing lodash):

arr.join().split("3,4").join("4,3").split(",").map(Number)

Upvotes: 1

Aadit M Shah
Aadit M Shah

Reputation: 74204

Is there an elegant way to do this in Lodash without the use of for loops?

Yes, you can use reduce as follows:

var array  = [1, 2, 3, 4, 5, 3, 4, 6, 3, 7, 4];

var result = _.reduce(array, swapAdjacentInOrder(3, 4), []);

alert(JSON.stringify(result));

function swapAdjacentInOrder(a, b) {
    return function (result, element) {
        var length = result.length;

        if (length > 0 && element === b) {
            var last = length - 1;

            if (result[last] === a) {
                result[last] = b;
                element = a;
            }
        }

        result[length] = element;

        return result;
    };
}
<script src="https://rawgit.com/lodash/lodash/master/lodash.min.js"></script>

However, the swapAdjacentInOrder function also has the following property:

var array  = [3, 4, 4, 4];

var result = _.reduce(array, swapAdjacentInOrder(3, 4), []);

alert(JSON.stringify(result)); // [4, 4, 4, 3]

function swapAdjacentInOrder(a, b) {
    return function (result, element) {
        var length = result.length;

        if (length > 0 && element === b) {
            var last = length - 1;

            if (result[last] === a) {
                result[last] = b;
                element = a;
            }
        }

        result[length] = element;

        return result;
    };
}
<script src="https://rawgit.com/lodash/lodash/master/lodash.min.js"></script>

If you don't want that then you can do the following updated swapAdjacentInOrder function:

var array  = [3, 4, 4, 4];

var result = _.reduce(array, swapAdjacentInOrder(3, 4), []);

alert(JSON.stringify(result)); // [4, 3, 4, 4]

function swapAdjacentInOrder(a, b) {
    return function (result, element) {
        var length = result.length;

        if (length > 0 && element === b) {
            var last = length - 1;

            if (result[last] !== a || last > 0 && result[last - 1] === b);
            else {
                result[last] = b;
                element = a;
            }
        }

        result[length] = element;

        return result;
    };
}
<script src="https://rawgit.com/lodash/lodash/master/lodash.min.js"></script>

Hope that helps.

Upvotes: 1

Related Questions