【发布时间】:2015-07-11 00:16:35
【问题描述】:
我想将一个数组拆分成数组对。
var arr = [2, 3, 4, 5, 6, 4, 3, 5, 5]
会
var newarr = [
[2, 3],
[4, 5],
[6, 4],
[3, 5],
[5]
]
【问题讨论】:
标签: javascript arrays
我想将一个数组拆分成数组对。
var arr = [2, 3, 4, 5, 6, 4, 3, 5, 5]
会
var newarr = [
[2, 3],
[4, 5],
[6, 4],
[3, 5],
[5]
]
【问题讨论】:
标签: javascript arrays
可以使用jsreduce
initialArray.reduce(function(result, value, index, array) {
if (index % 2 === 0)
result.push(array.slice(index, index + 2));
return result;
}, []);
【讨论】:
array.reduce((result, value, index, sourceArray) => index % 2 === 0 ? [...result, sourceArray.slice(index, index + 2)] : result, [])
Lodash 对此有一个方法:https://lodash.com/docs/4.17.10#chunk
_.chunk([2,3,4,5,6,4,3,5,5], 2);
// => [[2,3],[4,5],[6,4],[3,5],[5]]
【讨论】:
没有预先烘焙的功能可以做到这一点,但这里有一个简单的解决方案:
var splitPairs = function(arr) {
var pairs = [];
for (var i=0 ; i<arr.length ; i+=2) {
if (arr[i+1] !== undefined) {
pairs.push ([arr[i], arr[i+1]]);
} else {
pairs.push ([arr[i]]);
}
}
return pairs;
};
【讨论】:
arr 的奇数长度如何?
for(var i = 0; i < arr.length; i + 2)。索引未更新,因为 i + 2 未设置 i 值。 i += 2 有效,因为它设置了 i 值。这就是为什么尽可能使用 map/reduce 更好地实现功能!
另一个是已经发布的答案的混搭。添加它是因为阅读了答案后我仍然觉得事情可能更容易阅读:
var groups = [];
for(var i = 0; i < arr.length; i += 2)
{
groups.push(arr.slice(i, i + 2));
}
【讨论】:
end 大于序列的长度,slice 会一直提取到序列的末尾(arr.length)。
对于这种情况,我会使用lodash。
这是使用_.reduce的解决方案:
var newArr = _(arr).reduce(function(result, value, index) {
if (index % 2 === 0)
result.push(arr.slice(index, index + 2));
return result;
}, []);
var arr = [2,3,4,5,6,4,3,5,5];
var newArr = _(arr).reduce(function(result, value, index) {
if (index % 2 === 0)
result.push(arr.slice(index, index + 2));
return result;
}, []);
document.write(JSON.stringify(newArr)); // [[2,3],[4,5],[6,4],[3,5],[5]]
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/3.10.0/lodash.min.js"></script>
【讨论】:
可以在一行中将数组分组为对/块,而无需库:
function chunks(arr, size = 2) {
return arr.map((x, i) => i % size == 0 && arr.slice(i, i + size)).filter(x => x)
}
console.log(chunks([1, 2, 3, 4, 5, 6, 7])) // -> [[1, 2], [3, 4], [5, 6], [7]]
【讨论】:
现在有灵活的Array#flatMap(value, index, array):
const pairs = arr.flatMap((_, i, a) => i % 2 ? [] : [a.slice(i, i + 2)]);
还有可能更高效但看起来很傻的Array.from(source, mapfn?):
const pairs = Array.from({ length: arr.length / 2 }, (_, i) => arr.slice(i * 2, i * 2 + 2))
【讨论】:
与使用for 循环进行比较的方法略有不同。为了避免修改原始数组slice,由于 JS 通过引用传递对象,因此进行了浅拷贝。
function pairArray(a) {
var temp = a.slice();
var arr = [];
while (temp.length) {
arr.push(temp.splice(0,2));
}
return arr;
}
var array = [2,3,4,5,6,4,3,5,5];
var newArr = pairArray(array);
function pairArray(a) {
var temp = a.slice();
var arr = [];
while (temp.length) {
arr.push(temp.splice(0,2));
}
return arr;
}
document.write('<pre>' + JSON.stringify(newArr) + '</pre>');
【讨论】:
这是一个很好的通用解决方案:
function splitInto(array, size, inplace) {
var output, i, group;
if (inplace) {
output = array;
for (i = 0; i < array.length; i++) {
group = array.splice(i, size);
output.splice(i, 0, group);
}
} else {
output = [];
for (i = 0; i < array.length; i += size) {
output.push(array.slice(i, size + i));
}
}
return output;
}
对于你的情况,你可以这样称呼它:
var arr= [2,3,4,5,6,4,3,5,5];
var newarr = splitInto(arr, 2);
inplace 参数确定操作是否就地完成。
下面是一个演示:
function splitInto(array, size, inplace) {
var output, i, group;
if (inplace) {
output = array;
for (i = 0; i < array.length; i++) {
group = array.splice(i, size);
output.splice(i, 0, group);
}
} else {
output = [];
for (i = 0; i < array.length; i += size) {
output.push(array.slice(i, size + i));
}
}
return output;
}
var arr= [2,3,4,5,6,4,3,5,5];
var newarr = splitInto(arr, 2);
disp(newarr);
// or we can do it in-place...
splitInto(arr, 3, true);
disp(arr);
function disp(array) {
var json = JSON.stringify(array);
var text = document.createTextNode(json);
var pre = document.createElement('pre');
pre.appendChild(text);
document.body.appendChild(pre);
}
【讨论】:
这是另一个使用 lodash 助手的解决方案:
function toPairs(array) {
const evens = array.filter((o, i) => i % 2);
const odds = array.filter((o, i) => !(i % 2));
return _.zipWith(evens, odds, (e, o) => e ? [o, e] : [o]);
}
console.log(toPairs([2,3,4,5,6,4,3,5,5]));
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.13.1/lodash.min.js"></script>
【讨论】:
const items = [1, 2, 3, 4, 5];
const createBucket = (bucketItems, bucketSize) => buckets => {
return bucketItems.length === 0 ? buckets : [...buckets, bucketItems.splice(0, bucketSize)];
};
const bucketWithItems = items.reduce(createBucket([...items], 4), []);
【讨论】:
这是一个简短且更通用的解决方案:
function splitArrayIntoPairs(arr, n) {
var len = arr.length
var pairs = []
for (let i = 0; i < len; i += n) {
var temp = []
for (var j = i; j < (i + n); j++) {
if (arr[j] !== undefined) {
temp.push(arr[j])
}
}
pairs.push(temp)
}
return pairs
}
其中 arr 是您的数组,而 n 不是对
【讨论】:
这是另一个使用生成器函数的通用解决方案。
/**
* Returns a `Generator` of all unique pairs of elements from the given `iterable`.
* @param iterable The collection of which to find all unique element pairs.
*/
function* pairs(iterable) {
const seenItems = new Set();
for (const currentItem of iterable) {
if (!seenItems.has(currentItem)) {
for (const seenItem of seenItems) {
yield [seenItem, currentItem];
}
seenItems.add(currentItem);
}
}
}
const numbers = [1, 2, 3, 2];
const pairsOfNumbers = pairs(numbers);
console.log(Array.from(pairsOfNumbers));
// [[1,2],[1,3],[2,3]]
我喜欢这种方法的一点是,它不会消耗输入中的下一个项目,直到它真正需要它。如果您将生成器作为输入提供给它,这将特别方便,因为它会尊重其延迟执行。
【讨论】:
这结合了上面的一些答案,但没有 Object.fromEntires。输出类似于 minimist 的输出。
const splitParameters = (args) => {
const split = (arg) => (arg.includes("=") ? arg.split("=") : [arg]);
return args.reduce((params, arg) => [...params, ...split(arg)], []);
};
const createPairs = (args) =>
Array.from({ length: args.length / 2 }, (_, i) =>
args.slice(i * 2, i * 2 + 2)
);
const createParameters = (pairs) =>
pairs.reduce(
(flags, value) => ({
...flags,
...{ [value[0].replace("--", "")]: value[1] }
}),
{}
);
const getCliParameters = (args) => {
const pairs = createPairs(splitParameters(args));
const paramaters = createParameters(pairs);
console.log(paramaters);
return paramaters;
};
//const argsFromNodeCli = process.argv.slice(2); // For node
const testArgs = [
"--url",
"https://www.google.com",
"--phrases=hello,hi,bye,ok"
];
const output = getCliParameters(testArgs);
document.body.innerText = JSON.stringify(output);
【讨论】: