7

Let's say that I have the following array:

const myArray = ["q", "w", "e", "r", "t", "y"]

What I would like to do is to add an element between all the elements, like this:

myArray.someMethod("XXX")
// ["q", "XXX", "w", "XXX", "e", "XXX", "r", "XXX", "t", "XXX", "y"]

In a way, it is kinda what .join does, but I would like the output to be another array, instead of a string.

I know how to do this with a loop, but I would like to know is the "functional" way to achieve this.

Enrique Moreno Tent
  • 24,127
  • 34
  • 104
  • 189
  • Some time ago, I made a generalized method for this, you could check it if you like: https://stackoverflow.com/questions/53892270/insert-new-element-after-each-nt-h-array-element/53892730#53892730 – Shidersz Jan 15 '19 at 14:57

7 Answers7

8

Instead of an iterative approach, you could take a recursive approach by taking rest parameters and a check for the length of the rest array.

const
    zip = ([a, ...r], v) => r.length ? [a, v, ...zip(r, v)] : [a];

console.log(zip(["q", "w", "e", "r", "t", "y"], 'XXX'));
.as-console-wrapper { max-height: 100% !important; top: 0; }
Nina Scholz
  • 376,160
  • 25
  • 347
  • 392
4

In a functional programming way, an Array is a Monad which means it is flatMappable. FlatMap is an implementation of a Monadic bind operator which for an Array it maps an element to a new array and flatten them together.

With this idea, you just need to add a new value to the output array inside the flatMap function. See following

Array.prototype.someMethod = function(a){ return this.flatMap(i => [i,a]) }

myArray.someMethod("XXX")
// Array(12) [ "q", "XXX", "w", "XXX", "e", "XXX", "r", "XXX", "t", "XXX", … ]

The above example adds the XXX at the end of the Array, so we can ignore the last element from being padded by making use of the index argument of the flatMap as follows

Array.prototype.someMethod = function(a){ let L=this.length; return this.flatMap((n,i) => (i<L-1) ? [n,a] : [n]) }

myArray.someMethod("XXX")
// Array(11) [ "q", "XXX", "w", "XXX", "e", "XXX", "r", "XXX", "t", "XXX", "y"]
TaoPR
  • 5,932
  • 3
  • 25
  • 35
1

You can use .map() with .concat():

const data = ["q", "w", "e", "r", "t", "y"];
const str = "XXX";

const insertValue = (arr, val) => [].concat(
    ...arr.map((v, i) => (i > 0 ? [str, v] : v))
);

console.log(insertValue(data, str));
.as-console-wrapper { max-height: 100% !important; top: 0; }
Mohammad Usman
  • 37,952
  • 20
  • 92
  • 95
0

const myArray = ["q", "w", "e", "r", "t", "y"]
const joinStr = 'xxx';
console.log(myArray.join(','+ joinStr + ',').split(','));
Saad Mehmood
  • 691
  • 1
  • 7
  • 19
  • 2
    Will not work if `,`-the _glue_ is contained by any of the array element. – Tushar Jan 15 '19 at 12:07
  • @Tushar yes but you can change it to any unique kind of ```"glue"```. ```,``` is what I used for this example it can be sothing like ```@%``` may be. – Saad Mehmood Jan 15 '19 at 12:08
  • True. However, if data is coming from third-party service or it is user-entered, then you cannot guarantee about the uniqueness of the _glue_. – Tushar Jan 15 '19 at 12:12
0

You can use map() with flat()

const myArray = ["q", "w", "e", "r", "t", "y"];
const newArray = myArray.map((i) => {
   return [i, 'xxx']
}).flat();

console.log(newArray);
Tom M
  • 2,815
  • 2
  • 20
  • 47
0

You could use reduce to transform the original array and either put it in a two argument function or add it as a method of Array.prototype (if you really want the call method in the post):

const myArray = ["q", "w", "e", "r", "t", "y"]

// A function taking array and glue arguments

const interpose = (array, glue) => array.reduce(
   (acc, c,i,a) => (
        acc.push(c) && (i < a.length -1) && acc.push( glue),
        acc
    ), []
);

// As an array method

Array.prototype.interpose = function( glue) {
    return  this.reduce(
    (acc, c,i,a) => (
         acc.push(c) && (i < a.length -1) && acc.push( glue),
         acc
     ), []);
}

// Test

console.log( 'interpose( myArray, "XXX" = %s', interpose( myArray, "XXX"));
console.log( 'myArray.interpose("XXX")  = %s', myArray.interpose("XXX"));
traktor
  • 17,588
  • 4
  • 32
  • 53
0

You can join, since the default character of joining is comma, then change by surrounding each comma with ','+glue+',' finally split it by comma.

const myArray = ["q", "w", "e", "r", "t", "y"]

Array.prototype.someMethod = function(glue){
    return this.join().replaceAll(',',','+glue+',').split(',');
} 

console.log(myArray.someMethod("XXX"))
// ["q", "XXX", "w", "XXX", "e", "XXX", "r", "XXX", "t", "XXX", "y"]
XMehdi01
  • 5,538
  • 2
  • 10
  • 34