简体   繁体   中英

Map or flatmap that works like Array.prototype.join in Javascript

I find the functionality of Array.prototype.join very useful because it only applies the join value to the "inner" connections of the elements in the array. Like so:

['Hey', 'there'].join('-') // Hey-there

Where Array.protoype.map produces a 'leftover' dash in this example:

['Hey', 'there'].map(value => value + '-') // Hey-there-

I've been looking for a succinct way to map arrays without converting them to a string, possibly to a new array, like so:

// Intended behaviour ['Hey', 'there'].mapJoin('-') // ['Hey', '-', 'there']

I'm NOT looking for an imperative solution to the problem as I could write that myself and put it in a global import somewhere. I'm looking for a native way (ES6 is fine) to express it elegantly so I can write it in all my projects.

You could join with a wanted separator, and split by the addition comma (or any other value, if taken for join).

 var array = ['Hey', 'there'], separator = '-', result = array.join(',' + separator + ',').split(','); console.log(result); 

Another solution could be to take new indices and fill the previos index with the sepparator.

 var array = ['Hey', 'there'], separator = '-', result = Object.assign( [], ...array.map((v, i) => ({ [i * 2 - 1]: separator, [i * 2]: v })) ); console.log(result); 

You're looking for Ramda's intersperse .

R.intersperse('n', ['ba', 'a', 'a']); //=> ['ba', 'n', 'a', 'n', 'a']

Though it's implemented imperatively.

It's not exactly pretty or elegant, but

['Hey', 'there'].reduce(
  (acc, value, i, arr) => (acc.push(value), i < arr.length - 1 ? acc.push('-') : 0, acc),
  [],
)

Alternate version of @ AKX 's answer.

 const data = ['Hey', 'there']; const output = data.reduce((p, c, i, a) => p.concat(i < a.length -1 ? [c, '-'] : [c]), []); console.log(output) 

You can try this one

 const mapJoin = (arr, joiner) => { return arr.reduce( (curr, t) => curr.concat(t, joiner), []).slice(0, arr.length*2-1) } const data = ["Hey", "There"] console.log(mapJoin(data, "-")) 

A simple recursive encoding

 const intersperse = (sep, [ x, ...rest ]) => // base case; return empty result x === undefined ? [] // one remaining x, return singleton : rest.length === 0 ? [ x ] // default case; return pair of x and sep and recur : [ x, sep ] .concat (intersperse (sep, rest)) console.log ( intersperse ("~", []) // [] , intersperse ("~", [ 1 ]) // [ 1 ] , intersperse ("~", [ 1, 2 ]) // [ 1, ~, 2 ] , intersperse ("~", [ 1, 2, 3 ]) // [ 1, ~, 2, ~, 3 ] , intersperse ("~", [ 1, 2, 3, 4 ]) // [ 1, ~, 2, ~, 3, ~, 4 ] ) 

You're looking for the intersperse function, which is easy to define:

 const intersperse = (x, ys) => [].concat(...ys.map(y => [x, y])).slice(1); console.log(intersperse("-", ["Hey", "there"])); // ["Hey", "-", "there"] console.log(intersperse(0, [1, 2, 3])); // [1, 0, 2, 0, 3] console.log(intersperse(0, [])); // [] 

Alternatively, you could decompose it into smaller functions:

 const concat = xss => [].concat(...xss); const concatMap = (f, xs) => concat(xs.map(f)); const intersperse = (x, ys) => concatMap(y => [x, y], ys).slice(1); console.log(intersperse("-", ["Hey", "there"])); // ["Hey", "-", "there"] console.log(intersperse(0, [1, 2, 3])); // [1, 0, 2, 0, 3] console.log(intersperse(0, [])); // [] 

You can even install them on Array.prototype :

 Object.assign(Array.prototype, { concatenate() { return [].concat(...this); }, concatMap(f) { return this.map(f).concatenate(); }, intersperse(x) { return this.concatMap(y => [x, y]).slice(1); } }); console.log(["Hey", "there"].intersperse("-")); // ["Hey", "-", "there"] console.log([1, 2, 3].intersperse(0)); // [1, 0, 2, 0, 3] console.log([].intersperse(0)); // [] 

In Haskell, you'd write this as follows:

intersperse :: a -> [a] -> [a]
intersperse x = drop 1 . concatMap (\y -> [x, y])

Can you see the similarities?

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM