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]]