數組有沒有把這個數組優雅的,功能性的方式:的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