Compare and add in a single line of code?

Viewed 85

Given an array
[9,5,4,2,1,1,5,8,1,1]

is there a way to remove all the 1s and add equal amount of xs at the end. To get this
[9,5,4,2,5,8,x,x,x,x]

Am looking for a way to do this in one line. Curious if there is a technique here I may be missing or maybe there is none.

I am clearly wrong in my use of this in the below example. But gives you an idea of what I am trying to do.

let test = [9,5,4,2,1,1,5,8,1,1];

console.log(test.map(el => el !== 1 ?el :this.push('x'));

4 Answers

Using filter() and fill()

let test = [9, 5, 4, 2, 1, 1, 5, 8, 1, 1];

let res = test.filter(el => el !== 1)

res = res.concat(Array(test.length - res.length).fill('x'))

console.log(res);

Using reduce()

let test = [9, 5, 4, 2, 1, 1, 5, 8, 1, 1];

let res = test.reduceRight((a, e) => e !== 1 ? [e, ...a] : [...a, 'x'], [])

console.log(res);

You could take two loops to get the array reordered.

var array = [9, 5, 4, 2, 1, 1, 5, 8, 1, 1],
    j = 0;

console.log(...array);

for (let i = 0; i < array.length; i++) {
    if (array[i] !== 1) array[j++] = array[i];
}
while (j < array.length) array[j++] = 'x';

console.log(...array);

Basically the same wrapped in a forEach callback.

var array = [9, 5, 4, 2, 1, 1, 5, 8, 1, 1];

array.forEach((j => (v, i, a) => { if (i + 1 === a.length) while (j < a.length) a[j++] = 'x'; else if (v !== 1) a[j++] = v; })(0));

console.log(...array);

An even shorter approach with mapping of the values

var array = [9, 5, 4, 2, 1, 1, 5, 8, 1, 1];

array = array.map((j => (v, _, a) => { while (a[j] === 1) j++; return j in a ? a[j++] : 'x'; })(0));

console.log(...array);

EDIT: As is called out in the comments below, the manner in which .sort is leveraged in this solution is a bit strange (to put it generously). I would recommend looking to the other posted solutions for approaches that are a bit more robust.




It cannot be done (or at least done easily) in one operation/loop, but it can be done in a single line:

let test = [9,5,4,2,1,1,5,8,1,1];

let output = test.map((num) => num === 1 ? 'x' : num).sort((a,b) => b === 'x' ? -1 : 0)

console.log(output);

Your usage of this didn't make sense; in a loop operation you return the desired output (either explicitly or as an implicit return from a fat-arrow function).

So in the above example, we first use loop once with .map to return a new array that has all the 1s replaced with "x"s. We then loop over the newly returned array to .sort all the instances of "1" to the end of the array.

Re your use of this: you can't access the array that map is building from within the map callback, it isn't accessible to your code until map returns it.

Technically, you could do this with one expression on a single line:

console.log(Array.from(Object.assign(test.filter(el => el !== 1), {length: test.length})).map(el => el === undefined ? "x" : el));

That assumes no undefined entries in the original, which seems reasonable given the sample given.

Live Example:

let test = [9,5,4,2,1,1,5,8,1,1];

console.log(Array.from(Object.assign(test.filter(el => el !== 1), {length: test.length})).map(el => el === undefined ? "x" : el));
.as-console-wrapper {
    max-height: 100% !important;
}

But, I'd strongly advise against it. I'd just do it the simple way:

const result = test.filter(el => el !== 1);
while (result.length < test.length) {
    result.push("x");
}

Live Example:

let test = [9,5,4,2,1,1,5,8,1,1];

const result = test.filter(el => el !== 1);
while (result.length < test.length) {
    result.push("x");
}

console.log(result);
.as-console-wrapper {
    max-height: 100% !important;
}

Or perhaps

const result = test.filter(el => el !== 1);
result.push(...Array(test.length - result.length).fill("x"));

Live Example:

let test = [9,5,4,2,1,1,5,8,1,1];

const result = test.filter(el => el !== 1);
result.push(...Array(test.length - result.length).fill("x"));

console.log(result);
.as-console-wrapper {
    max-height: 100% !important;
}

...but for me even that is a bit overcomplicated.

Related