数组有没有把这个数组优雅的,功能性的方式:的JavaScript:请值对的数组形成价值观
[ 1, 5, 9, 21 ]
这个
[ [1, 5], [5, 9], [9, 21] ]
我知道我可以forEach
数组并收集值来创建一个新的数组。在_.lodash
中有没有使用forEach
的优雅方法?
数组有没有把这个数组优雅的,功能性的方式:的JavaScript:请值对的数组形成价值观
[ 1, 5, 9, 21 ]
这个
[ [1, 5], [5, 9], [9, 21] ]
我知道我可以forEach
数组并收集值来创建一个新的数组。在_.lodash
中有没有使用forEach
的优雅方法?
您可以映射拼接数组并检查索引。如果它不为零,则取前者,否则为原始数组的第一个元素。
var array = [1, 5, 9, 21],
result = array.slice(1).map((a, i, aa) => [i ? aa[i - 1] : array[0], a]);
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
更短的版本,由Bergi的建议:
var array = [1, 5, 9, 21],
result = array.slice(1).map((a, i) => [array[i], a]);
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
使用map
一种快速的方法是:
const arr = [ 1, 5, 9, 21 ];
const grouped = arr.map((el, i) => [el, arr[i+1]]).slice(0, -1);
console.log(grouped);
.as-console-wrapper { max-height: 100% !important; top: 0; }
仍然最具可读性,也可以被其他队友所理解。 – Jankapunkt
我也喜欢这样的可读性。 – Norris
@Norris我终于删除了'pop'指令。现在更优雅的代码。 – Diego
如果你愿意用另一种功能库“ramda”,aperture是你正在寻找的功能。从ramda文档采取
实例:
R.aperture(2, [1, 2, 3, 4, 5]); //=> [[1, 2], [2, 3], [3, 4], [4, 5]]
R.aperture(3, [1, 2, 3, 4, 5]); //=> [[1, 2, 3], [2, 3, 4], [3, 4, 5]]
R.aperture(7, [1, 2, 3, 4, 5]); //=> []
容易与array.reduce
完成。下面的内容是使用数组作为聚合器,跳过第一个项目,然后在每个项目之后将前一个项目和当前项目作为一对推送到数组。
const arr = [ 1, 5, 9, 21 ];
const chunked = arr.reduce((p, c, i, a) => i === 0 ? p : (p.push([c, a[i-1]]), p), []);
console.log(chunked);
展开版本会是什么样子:
const arr = [1, 5, 9, 21];
const chunked = arr.reduce(function(previous, current, index, array) {
if(index === 0){
return previous;
} else {
previous.push([ current, array[index - 1]]);
return previous;
}
}, []);
console.log(chunked);
我注意到,目前的解决方案,在某种程度上,都显得超前或落后( arr[i + 1]
或arr[i - 1]
)。
探索一种使用reduce
和函数闭包中定义的附加数组来存储待完成分区的方法可能会很有用。
注:
part
没有,只有2项工作,但通过使用数组时是一个数组,我们扩展了方法工作n
大小项目集shift
的粉丝,你可以使用组合slice
并重新定义part
,但我认为这是安全的。length
少于所需数目的元素不会返回const partition = partitionSize => arr => {
const part = [];
return arr.reduce((parts, x) => {
part.push(x);
if (part.length === partitionSize) {
parts.push(part.slice());
part.shift();
}
return parts;
}, []);
};
const makePairs = partition(2);
const makeTrios = partition(3);
const pairs = makePairs([1,2,3,4,5,6]);
const trios = makeTrios([1,2,3,4,5,6]);
console.log("partition(2)", JSON.stringify(pairs));
console.log("partition(3)", JSON.stringify(trios));
我敢肯定有一个优雅的方式,程序,但是,数学我不禁看到每个新对具有1从原来的数组索引的差异。
如果你(后)有必要把你的阵列[ 1, 5, 9, 21, 33 ]
为[ [1, 9], [5, 21], [9, 33] ]
,您可以使用一个事实,即指数之间的差异是2
如果为1折射率差创建代码,延长这很容易。
这里的slide
它有两个参数来控制片的大小和多少个元素片
slide
从其他的答案不同,这里给你这些控制参数之间被丢弃。其他的答案在这里只限于生产只有2片,或递增1片,每次
// take :: (Int, [a]) -> [a]
const take = (n, xs) =>
xs.slice(0, n)
// drop :: (Int, [a]) -> [a]
const drop = (n, xs) =>
xs.slice(n)
// slice :: (Int, Int, [a]) -> [[a]]
const slide = (m, n, xs) =>
xs.length > m
? [take(m, xs), ...slide(m, n, drop(n, xs))]
: [xs]
const arr = [0,1,2,3,4,5,6]
// log helper improves readability of output in stack snippet
const log = x => console.log(JSON.stringify(x))
log(slide(1, 1, arr))
// [[0],[1],[2],[3],[4],[5],[6]]
log(slide(1, 2, arr))
// [[0],[2],[4],[6]]
log(slide(2, 1, arr))
// [[0,1],[1,2],[2,3],[3,4],[4,5],[5,6]]
log(slide(2, 2, arr))
// [[0,1],[2,3],[4,5],[6]]
log(slide(3, 1, arr))
// [[0,1,2],[1,2,3],[2,3,4],[3,4,5],[4,5,6]]
log(slide(3, 2, arr))
// [[0,1,2],[2,3,4],[4,5,6]]
log(slide(3, 3, arr))
// [[0,1,2],[3,4,5],[6]]
如果由于某种原因你不想slide
包括部分片,(切片小于m
),我们可以编辑它
// slice :: (Int, Int, [a]) -> [[a]]
const slide = (m, n, xs) =>
xs.length > m
? [take(m, xs), ...slide(m, n, drop(n, xs))]
: [] // <- return [] instead of [xs]
log(slide(2, 2, arr))
// now prints: [[0,1],[2,3],[4,5]]
// instead of: [[0,1],[2,3],[4,5],[6]]
你为什么要这样?你的目标是什么? – niceman
https://lodash.com/docs/4.17.4#chunk。顺便说一下,该操作的名称通常是*称为“分区”,该链接是'lodash分区阵列'的第一个谷歌命中。 –
@niceman - 这个函数最好叫做'相邻对' - 我以前用过这个概念。贾里德史密斯 - 那不一样。看看OP的例子 – aaaaaa