将数组中的每隔一个值移动到一个新数组中

5

我有两个一维数组,aba包含数值,而b为空。数组a的长度是偶数。我想从a中删除每隔一个值,并按照它们在a中的顺序将它们移动到b中。

var a = [1, 2, 3, 4, 5, 6], b = [];

成为

var a = [1, 3, 5], b = [2, 4, 6];

我认为filter会起作用,但是它的性能并不令人满意,因为a的平均长度为300-400。

b = a.filter((i, idx) => {
    return idx % 2 == 0;
});
a = a.filter((i, idx) => {
    return idx % 2 == 1;
});

我也一直在研究lodash,看看这个库是否有任何可以帮助我的东西,唯一接近我所寻找的函数是_.chunk(array, \[size=1\])

我感激所有帮助我找到更好、更快方法的人。


过滤一个仅有400个元素的小数组应该几乎是瞬间完成的。你说你对性能不满意?你有注意到延迟吗?虽然可以在单次迭代中完成,但这并不会有太大的区别。 - salezica
你可以对给出的答案进行基准测试,看看lodash在性能上与原生JavaScript相比表现如何,这将非常有趣。 - Hinrich
@slezica 我同意,如果只有400个元素,这不会有明显的差异。但是,如果这个操作被执行了很多次,它可能会产生影响。 - Hinrich
@Hinrich,好主意,我会用你的所有答案建立一个jsperf测试。 - Magnus
1
这是一个性能测试,感谢您的帮助! https://jsperf.com/move-every-other-value-from-array-into-a-new-array - Magnus
4个回答

4

既然你提到了lodash,你可以使用_.partition来实现:

let a = [1, 2, 3, 4, 5, 6];
let b = [];
let i = -1;

[a, b] = _.partition(a, (item) => i++ % 2);

console.log(a);
console.log(b);
<script src="https://cdn.jsdelivr.net/lodash/4.17.4/lodash.min.js"></script>

分区的谓词是恒等函数,不包括项目的索引,因此这需要一个外部索引i的妥协。

当然,您可以将此功能封装到自己的函数中:

const splitEvenOdd = (array, i = -1) => _.partition(array, (item) => i++ % 2);

let a = [1, 2, 3, 4, 5, 6];
let b = [];

[a, b] = splitEvenOdd(a);

console.log(a);
console.log(b);
<script src="https://cdn.jsdelivr.net/lodash/4.17.4/lodash.min.js"></script>


2

使用原始的JavaScript ES5,简单而干净。

var a = [1, 2, 3, 4, 5, 6], b = [];

for(var i = a.length-1; i >= 0; i--) {
  if(i % 2 === 1) {
    b.unshift(a.splice(i, 1)[0])
  }
}

基本上,它通过反向迭代 a,如果条件为真,则将该项拆分并添加为 b 的第一项。

2

要循环遍历源代码一次,可以根据索引将值添加到特定的数组中。例如:

const source = [1, 2, 3, 4, 5, 6];

let arrs = [[],[]];
for(let i = 0; i< source.length; i++)
 arrs[i%2].push(source[i]);
let [a,b] = arrs;  
  
console.log(a);
console.log(b);

或者,如果修改原始数组很重要,可以直接迭代填充a,因为正在处理的索引始终在填充的索引之前:

let a = [1, 2, 3, 4, 5, 6], b= [];

for(let i = 0; i< a.length; i++)
 (i % 2 ? b : a)[Math.floor(i/2)] = a[i];
  
a.splice(a.length/2);
  
console.log(a);
console.log(b);


优秀的答案,使用原生JS...我更喜欢它,而不是依赖于库。 - chazsolo

1

在这种情况下,您可以获得的最佳性能是O(n)或线性时间,因为您必须遍历整个数组。减少循环次数可能会有所帮助。

var a=[];
var b=[];
function splitArray(arr)
{
    for (var i=0;i<arr.length;++i)
        {
            if (arr[i]%2 == 0)
                b.push(arr[i]);
            else
                a.push(arr[i]); 
        }
}

这样做可以将原始数组的迭代次数从2减少到1。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接