點燈坊

失くすものさえない今が強くなるチャンスよ

如何使 Array 中的 0 挪到最後 ?

Sam Xiao's Avatar 2019-10-01

若 array 中遍佈了一堆 0,我們希望將 非 0 部分全部往前移,而 0 全部挪到最後,該如何實現呢 ?

Version

macOS Mojave 10.14.6
VS Code 1.38.1
Quokka 1.0.253
Ramda 0.26.1
Wink-fp 0.1.2

Functional

let data = [0, 1, 4, 8, 0, 1];

let fn = arr => {
  let arr0 = arr.filter(x => x !== 0);
  let arr1 = arr.filter(x => x === 0);

  return arr0.concat(arr1);
};

fn(data); // ?

分別使用 filter() 取得 非 00 的部分,最後使用 concat() 將兩個 array 合併。

end000

Point-free

import { filter, concat, converge, equals, complement } from 'ramda';

let data = [0, 1, 4, 8, 0, 1];

let fn = converge(
  concat, [
    filter((complement(equals))(0)),
    filter(equals(0))
  ]
);

fn(data); // ?

經觀察 concat() 為最後執行 function,且 concat() 的第一個 argument 與 第二個 argument 都必須經過同一個 arr argument 轉換,符合 coverge() 要求。

filter() 的 callback 可藉由 equals()complement(equals) 產生。

end001

Wink-fp

import { filter, concat, converge, equals, complement } from 'ramda';
import { nequals } from 'wink-fp';

let data = [0, 1, 4, 8, 0, 1];

let fn = converge(
  concat, [
    filter(nequals(0)),
    filter(equals(0))
  ]
);

fn(data); // ?

可改用 Wink-fp 的 nequls() 取代 complement(equals),語意更佳。

end001

Conclusion

  • 一個用 imperative 看似麻煩的問題,若使用 functional 解異常簡單,亦可使用 Ramda 的 converge() 與 Wink-fp 的 nequals() 繼續重構

Reference

Ramda, concat()
Ramda, filter()
Ramda, converge()
Ramda, equals()
Ramda, complement