Я нахожу функциональность Array.prototype.join очень полезной, потому что она применяет значение соединения только к «внутренним» соединениям элементов в массиве. Вот так:
['Hey', 'there'].join('-') // Hey-there
Где Array.protoype.map в этом примере выдает «оставшееся» тире:
['Hey', 'there'].map(value => value + '-') // Hey-there-
Я искал лаконичный способ сопоставления массивов без преобразования их в строку, возможно, в новый массив, например:
// Intended behaviour
['Hey', 'there'].mapJoin('-') // ['Hey', '-', 'there']
Я НЕ ищу обязательного решения проблемы, так как я мог бы написать это сам и поместить его где-нибудь в глобальный импорт. Я ищу собственный способ (ES6 в порядке), чтобы выразить это элегантно так что я могу писать это во всех своих проектах.



![Безумие обратных вызовов в javascript [JS]](https://i.imgur.com/WsjO6zJb.png)


Это не совсем красиво или элегантно, но
['Hey', 'there'].reduce(
(acc, value, i, arr) => (acc.push(value), i < arr.length - 1 ? acc.push('-') : 0, acc),
[],
)
Альтернативная версия ответа @ AKX.
const data = ['Hey', 'there'];
const output = data.reduce((p, c, i, a) => p.concat(i < a.length -1 ? [c, '-'] : [c]), []);
console.info(output)Вы можете присоединиться к желаемому разделителю и разделить добавочной запятой (или любым другим значением, если оно выбрано для соединения).
var array = ['Hey', 'there'],
separator = '-',
result = array.join(',' + separator + ',').split(',');
console.info(result);Другое решение - взять новые индексы и заполнить предыдущий индекс разделителем.
var array = ['Hey', 'there'],
separator = '-',
result = Object.assign(
[],
...array.map((v, i) => ({ [i * 2 - 1]: separator, [i * 2]: v }))
);
console.info(result);Вы ищете Рамда вкрапления.
R.intersperse('n', ['ba', 'a', 'a']); //=> ['ba', 'n', 'a', 'n', 'a']
Хотя в обязательном порядке это реализовано.
Вы можете попробовать это
const mapJoin = (arr, joiner) => {
return arr.reduce( (curr, t) => curr.concat(t, joiner), []).slice(0, arr.length*2-1)
}
const data = ["Hey", "There"]
console.info(mapJoin(data, "-"))Простая рекурсивная кодировка
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.info
( 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 ]
)Вы ищете функцию intersperse, которую легко определить:
const intersperse = (x, ys) => [].concat(...ys.map(y => [x, y])).slice(1);
console.info(intersperse("-", ["Hey", "there"])); // ["Hey", "-", "there"]
console.info(intersperse(0, [1, 2, 3])); // [1, 0, 2, 0, 3]
console.info(intersperse(0, [])); // []В качестве альтернативы вы можете разложить его на более мелкие функции:
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.info(intersperse("-", ["Hey", "there"])); // ["Hey", "-", "there"]
console.info(intersperse(0, [1, 2, 3])); // [1, 0, 2, 0, 3]
console.info(intersperse(0, [])); // []Вы даже можете установить их на 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.info(["Hey", "there"].intersperse("-")); // ["Hey", "-", "there"]
console.info([1, 2, 3].intersperse(0)); // [1, 0, 2, 0, 3]
console.info([].intersperse(0)); // []В Haskell вы бы написали это так:
intersperse :: a -> [a] -> [a]
intersperse x = drop 1 . concatMap (\y -> [x, y])
Вы видите сходство?