Say I have an array var arr = [1, 2, 3]
, and I want to separate each element by an element eg. var sep = "&"
, so the output is [1, "&", 2, "&", 3]
.
假设我有一个数组var arr =[1,2,3],我想用一个元素eg来分隔每个元素。9月var = " & ",所以输出(1”和“2“&”,3]。
Another way to think about it is I want to do Array.prototype.join (arr.join(sep)
) without the result being a string (because the elements and separator I am trying to use are Objects, not strings).
另一种思考方法是我想做array。prototype。join(arr.join, sep)没有结果是字符串(因为我要使用的元素和分隔符是对象,而不是字符串)。
Is there a functional/nice/elegant way to do this in either es6/7 or lodash without something that feels clunky like:
在es6/7或lodash中,有没有一种功能/美观/优雅的方法来实现这一点?
_.flatten(arr.map((el, i) => [el, i < arr.length-1 ? sep : null])) // too complex
or
或
_.flatten(arr.map(el => [el, sep]).slice(0,-1) // extra sep added, memory wasted
or even
甚至
arr.reduce((prev,curr) => { prev.push(curr, sep); return prev; }, []).slice(0,-1)
// probably the best out of the three, but I have to do a map already
// and I still have the same problem as the previous two - either
// inline ternary or slice
Edit: Haskell has this function, called intersperse
编辑:Haskell有这个功能,叫做intersperse
10 个解决方案
#1
12
Using a generator:
使用一台发电机:
function *intersperse(a, delim) {
let first = true;
for (const x of a) {
if (!first) yield delim;
first = false;
yield x;
}
}
console.log([...intersperse(array, '&')]);
Thanks to @Bergi for pointing out the useful generalization that the input could be any iterable.
感谢@Bergi指出输入可以是任何可迭代的有用概括。
If you don't like using generators, then
如果您不喜欢使用生成器,那么
[].concat(...a.map(e => ['&', e])).slice(1)
#2
6
A spread and explicit return in reducing function will make it more terse:
减缩函数的扩展和显式返回将使其更简洁:
const intersperse = (arr, sep) => arr.reduce((a,v)=>[...a,v,sep],[]).slice(0,-1)
// intersperse([1,2,3], 'z')
// [1, "z", 2, "z", 3]
#3
4
In ES6, you'd write a generator function that can produce an iterator which yields the input with the interspersed elements:
在ES6中,您将编写一个生成器函数,该函数可以生成一个迭代器,该迭代器产生带有穿插元素的输入:
function* intersperse(iterable, separator) {
const iterator = iterable[Symbol.iterator]();
const first = iterator.next();
if (first.done) return;
else yield first.value;
for (const value of iterator) {
yield separator;
yield value;
}
}
console.log(Array.from(intersperse([1, 2, 3], "&")));
#4
3
One straightforward approach could be like feeding the reduce function with an initial array in size one less than the double of our original array, filled with the character to be used for interspersing. Then mapping the elements of the original array at index i to 2*i in the initially fed target array would do the job perfectly..
一种简单的方法可能是使用小于原始数组的2倍大小的初始数组填充reduce函数,其中填充用于插入的字符。然后将原始数组的元素映射到初始化的目标数组中的2*i,这样就可以完美地完成任务了。
In this approach i don't see (m)any redundant operations. Also since we are not modifying any of the array sizes after they are set, i wouldn't expect any background tasks to run for memory reallocation, optimization etc. One other good part is using the standard array methods since they check all kinds of mismatch and whatnot.
在这种方法中,我没有看到(m)任何冗余操作。此外,由于我们在设置后没有修改任何数组大小,所以我不会期望任何后台任务会运行到内存重新分配、优化等方面。
This function returns a new array, in which the called upon array's items are interspersed with the provided argument.
该函数返回一个新数组,其中调用的数组的项与提供的参数穿插在一起。
var arr = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
Array.prototype.intersperse = function(s){
return this.reduce((p,c,i) => (p[2*i]=c,p), new Array(2*this.length-1).fill(s));
}
document.write("<pre>" + JSON.stringify(arr.intersperse("&")) + "</pre>");
#5
2
javascript has a method join() and split()
javascript有一个方法join()和split()
var arr = ['a','b','c','d'];
arr = arr.join('&');
document.writeln(arr);
Output should be: a&b&c&d
输出应该:a b c d
now split again:
现在又分:
arr = arr.split("");
arr is now:
加勒比海盗现在:
arr = ['a','&','b','&','c','&','d'];
#6
1
Using reduce
but without slice
使用减少,但没有切片
var arr = ['a','b','c','d'];
var lastIndex = arr.length-1;
arr.reduce((res,x,index)=>{
res.push(x);
if(lastIndex !== index)
res.push('&');
return res;
},[]);
#7
0
If you have Ramda in your dependencies or if willing to add it, there is intersperse
method there.
如果您的依赖项中有Ramda,或者如果愿意添加的话,可以在其中添加一些方法。
From the docs:
从文档:
Creates a new list with the separator interposed between elements.
创建一个包含分隔符的新列表。
Dispatches to the intersperse method of the second argument, if present.
如果存在,发送到第二个参数的穿插方法。
R.intersperse('n', ['ba', 'a', 'a']); //=> ['ba', 'n', 'a', 'n', 'a']
Or you can check out the source for one of the ways to do it in your codebase. https://github.com/ramda/ramda/blob/v0.24.1/src/intersperse.js
或者您可以在代码库中查看源代码,了解其中的一种方法。https://github.com/ramda/ramda/blob/v0.24.1/src/intersperse.js
#8
0
if (!Array.prototype.intersperse) {
Object.defineProperty(Array.prototype, 'intersperse', {
value: function(something) {
if (this === null) {
throw new TypeError( 'Array.prototype.intersperse ' +
'called on null or undefined' );
}
var isFunc = (typeof something == 'function')
return this.concat.apply([],
this.map(function(e,i) {
return i ? [isFunc ? something(this[i-1]) : something, e] : [e] }.bind(this)))
}
});
}
#9
0
you can also use the following:
你也可以使用以下资料:
var arr =['a', 'b', 'c', 'd'];
arr.forEach(function(element, index, array){
array.splice(2*index+1, 0, '&');
});
arr.pop();
#10
-1
Updated for objects not using join method:
更新未使用join方法的对象:
for (var i=0;i<arr.length;i++;) {
newarr.push(arr[i]);
if(i>0) {
newarr.push('&');
}
}
newarr should be:
newarr应该是:
newarr = ['a','&','b','&','c','&','d'];
#1
12
Using a generator:
使用一台发电机:
function *intersperse(a, delim) {
let first = true;
for (const x of a) {
if (!first) yield delim;
first = false;
yield x;
}
}
console.log([...intersperse(array, '&')]);
Thanks to @Bergi for pointing out the useful generalization that the input could be any iterable.
感谢@Bergi指出输入可以是任何可迭代的有用概括。
If you don't like using generators, then
如果您不喜欢使用生成器,那么
[].concat(...a.map(e => ['&', e])).slice(1)
#2
6
A spread and explicit return in reducing function will make it more terse:
减缩函数的扩展和显式返回将使其更简洁:
const intersperse = (arr, sep) => arr.reduce((a,v)=>[...a,v,sep],[]).slice(0,-1)
// intersperse([1,2,3], 'z')
// [1, "z", 2, "z", 3]
#3
4
In ES6, you'd write a generator function that can produce an iterator which yields the input with the interspersed elements:
在ES6中,您将编写一个生成器函数,该函数可以生成一个迭代器,该迭代器产生带有穿插元素的输入:
function* intersperse(iterable, separator) {
const iterator = iterable[Symbol.iterator]();
const first = iterator.next();
if (first.done) return;
else yield first.value;
for (const value of iterator) {
yield separator;
yield value;
}
}
console.log(Array.from(intersperse([1, 2, 3], "&")));
#4
3
One straightforward approach could be like feeding the reduce function with an initial array in size one less than the double of our original array, filled with the character to be used for interspersing. Then mapping the elements of the original array at index i to 2*i in the initially fed target array would do the job perfectly..
一种简单的方法可能是使用小于原始数组的2倍大小的初始数组填充reduce函数,其中填充用于插入的字符。然后将原始数组的元素映射到初始化的目标数组中的2*i,这样就可以完美地完成任务了。
In this approach i don't see (m)any redundant operations. Also since we are not modifying any of the array sizes after they are set, i wouldn't expect any background tasks to run for memory reallocation, optimization etc. One other good part is using the standard array methods since they check all kinds of mismatch and whatnot.
在这种方法中,我没有看到(m)任何冗余操作。此外,由于我们在设置后没有修改任何数组大小,所以我不会期望任何后台任务会运行到内存重新分配、优化等方面。
This function returns a new array, in which the called upon array's items are interspersed with the provided argument.
该函数返回一个新数组,其中调用的数组的项与提供的参数穿插在一起。
var arr = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
Array.prototype.intersperse = function(s){
return this.reduce((p,c,i) => (p[2*i]=c,p), new Array(2*this.length-1).fill(s));
}
document.write("<pre>" + JSON.stringify(arr.intersperse("&")) + "</pre>");
#5
2
javascript has a method join() and split()
javascript有一个方法join()和split()
var arr = ['a','b','c','d'];
arr = arr.join('&');
document.writeln(arr);
Output should be: a&b&c&d
输出应该:a b c d
now split again:
现在又分:
arr = arr.split("");
arr is now:
加勒比海盗现在:
arr = ['a','&','b','&','c','&','d'];
#6
1
Using reduce
but without slice
使用减少,但没有切片
var arr = ['a','b','c','d'];
var lastIndex = arr.length-1;
arr.reduce((res,x,index)=>{
res.push(x);
if(lastIndex !== index)
res.push('&');
return res;
},[]);
#7
0
If you have Ramda in your dependencies or if willing to add it, there is intersperse
method there.
如果您的依赖项中有Ramda,或者如果愿意添加的话,可以在其中添加一些方法。
From the docs:
从文档:
Creates a new list with the separator interposed between elements.
创建一个包含分隔符的新列表。
Dispatches to the intersperse method of the second argument, if present.
如果存在,发送到第二个参数的穿插方法。
R.intersperse('n', ['ba', 'a', 'a']); //=> ['ba', 'n', 'a', 'n', 'a']
Or you can check out the source for one of the ways to do it in your codebase. https://github.com/ramda/ramda/blob/v0.24.1/src/intersperse.js
或者您可以在代码库中查看源代码,了解其中的一种方法。https://github.com/ramda/ramda/blob/v0.24.1/src/intersperse.js
#8
0
if (!Array.prototype.intersperse) {
Object.defineProperty(Array.prototype, 'intersperse', {
value: function(something) {
if (this === null) {
throw new TypeError( 'Array.prototype.intersperse ' +
'called on null or undefined' );
}
var isFunc = (typeof something == 'function')
return this.concat.apply([],
this.map(function(e,i) {
return i ? [isFunc ? something(this[i-1]) : something, e] : [e] }.bind(this)))
}
});
}
#9
0
you can also use the following:
你也可以使用以下资料:
var arr =['a', 'b', 'c', 'd'];
arr.forEach(function(element, index, array){
array.splice(2*index+1, 0, '&');
});
arr.pop();
#10
-1
Updated for objects not using join method:
更新未使用join方法的对象:
for (var i=0;i<arr.length;i++;) {
newarr.push(arr[i]);
if(i>0) {
newarr.push('&');
}
}
newarr should be:
newarr应该是:
newarr = ['a','&','b','&','c','&','d'];