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.