4

数组有没有把这个数组优雅的,功能性的方式:的JavaScript:请值对的数组形成价值观

[ 1, 5, 9, 21 ]

这个

[ [1, 5], [5, 9], [9, 21] ]

我知道我可以forEach数组并收集值来创建一个新的数组。在_.lodash中有没有使用forEach的优雅方法?

+0

你为什么要这样?你的目标是什么? – niceman

+1

https://lodash.com/docs/4.17.4#chunk。顺便说一下,该操作的名称通常是*称为“分区”,该链接是'lodash分区阵列'的第一个谷歌命中。 –

+3

@niceman - 这个函数最好叫做'相邻对' - 我以前用过这个概念。贾里德史密斯 - 那不一样。看看OP的例子 – aaaaaa

回答

5

您可以映射拼接数组并检查索引。如果它不为零,则取前者,否则为原始数组的第一个元素。

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; }

+0

谢谢你的造型技巧! – Diego

+0

谢谢,除了使用Ramda之外,这看起来像最干净的方式。 – Norris

+0

为什么不只是'(a,i)=> [array [i],a]'? – Bergi

3

使用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; }

+3

仍然最具可读性,也可以被其他队友所理解。 – Jankapunkt

+1

我也喜欢这样的可读性。 – Norris

+0

@Norris我终于删除了'pop'指令。现在更优雅的代码。 – Diego

1

如果你愿意用另一种功能库“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]); //=> [] 
+0

拉姆达实际上看起来非常好。它正是我所期待的。 – Norris

+0

我更喜欢它比lodash/fp - 但维护人员不那么积极,花了很多时间讨论而不是编码。选择你的毒药:) – aaaaaa

2

容易与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);

0

我注意到,目前的解决方案,在某种程度上,都显得超前或落后( 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));

0

你可以做一个没有初始的.reduce()只是sinle衬垫如下:

var arr = [ 1, 5, 9, 21 ], 
 
    pairs = arr.reduce((p,c,i) => i == 1 ? [[p,c]] : p.concat([[p[p.length-1][1],c]])); 
 
console.log(pairs);

+0

这不适用于空阵列。为什么不使用初始参数?这是一个更短的在线。 – Bergi

+0

@Bergi当然显然,如果你不想陷入“没有初始值的空阵列减少”的坑中,你最好采取预防措施..但这个显然是一个伪代码。然而,主要的问题基本上是当输入是'[1]'时。 – Redu

0

我敢肯定有一个优雅的方式,程序,但是,数学我不禁看到每个新对具有1从原来的数组索引的差异。

如果你(后)有必要把你的阵列[ 1, 5, 9, 21, 33 ][ [1, 9], [5, 21], [9, 33] ],您可以使用一个事实,即指数之间的差异是2

如果为1折射率差创建代码,延长这很容易。

0

这里的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]]