簡體   English   中英

使用 Ramda 映射和過濾對象

[英]Map and filter an object using Ramda

我正在學習Ramda和我有點困惑如何構建這個lodash下面使用鏈Ramda Ramda為其操作返回函數而不是實際值,這似乎是函數式編程的焦點,但是在這個示例中,我有第二個參數localRegex ,它不是主要參數。 它似乎不可能得到這個被完全復制,而不包裹Ramda功能和使用.apply().call()來傳播包裝的函數參數的Ramda功能,這似乎再使用更復雜的lodash .

var _ = require("lodash")
var R = require("ramda")

var localRegex = /^.\.\/|^.\/|^\//

function getRecursiveDeps(deps, localRegex){
  return _.chain(deps)
    .map(function(dep){
      return dep.source.value
    })
    .filter(function(dep){
      return dep.match(localRegex)
    })
    .value()
}

var items = [
  {
    "source": {
      "value": "./foo"
    }
  },
  {
    "source": {
      "value": "bar"
    }
  }
]

console.log(getRecursiveDeps(items, localRegex))

這是我所擁有的,但它不起作用。

var getRecursiveDeps = R.chain(
  R.map(function(dependency){
    return dependency.source.value
  }),
  R.filter(function(value){
    return value.match(localRegex)
  })
)

有沒有辦法讓Ramda使用主變量進行鏈接並傳遞localRegex 有沒有辦法復制的getRecursiveDeps使用lodashRamda

有一個關於如何談了很多Ramda是功能齊全, underscorelodash都沒有。 但在這種情況下, getRecursiveDeps是一個從lodash返回值的lodash 當您從創建一個這樣的功能lodashunderscore的結果是一樣的,當涉及到包裝它,在這種情況下會怎樣使用是振作但只是更多的工作RamdaLodash

R.chain做了一些與_.chain完全不同的_.chain 根據當前文檔,它的類型是(a -> [b]) -> [a] -> [b] ,盡管它的實際類型更通用。 將其視為“平面地圖”功能。

你真正想要的是R.compose或其從左到右的等效R.pipe

如果函數的目標是找到局部依賴關系,我認為將模式嵌入到函數中似乎是合適的。 我會這樣寫:

// getLocalDeps :: [{ source :: { value :: String }}] -> [String]
const getLocalDeps =
R.pipe(R.map(R.path(['source', 'value'])),
       R.filter(R.test(/^[.]{0,2}[/]/)));

getLocalDeps(items);  // => ['./foo']

我對名稱getRecursiveDeps有點困惑,因為該函數不是遞歸的。 getLocalDeps似乎更合適。


如果您想參數化模式,我建議將getLocalDeps分成更小的部分:

// isLocal :: String -> Boolean
const isLocal = R.test(/^[.]{0,2}[/]/);

// getDeps :: [{ source :: { value :: String }}] -> [String]
const getDeps = R.map(R.path(['source', 'value']));

// getLocalDeps :: [{ source :: { value :: String }}] -> [String]
const getLocalDeps = R.pipe(getDeps, R.filter(isLocal));

然后,您可以根據這些構建塊定義其他功能:

// getNonLocalDeps :: [{ source :: { value :: String }}] -> [String]
const getNonLocalDeps = R.pipe(getDeps, R.reject(isLocal));

// getLocalJsonDeps :: [{ source :: { value :: String }}] -> [String]
const getLocalJsonDeps = R.pipe(getLocalDeps, R.filter(R.test(/[.]json$/)));

這樣做的另一種方法,無積分並保留您現有的 API 是這樣的:

// getLocalDeps :: [{ source :: { value :: String }}] -> RegExp -> [String]
const getLocalDeps =  R.useWith(
  R.flip(R.call),
  R.map(R.path(['source', 'value'])),
  R.pipe(R.unary(R.test), R.filter)
);

localDeps(items, localRegex); //=> ["./foo"]

函數的最后一行對我來說感覺有點不幸,這個問題讓我打開了一個關於恢復最近對庫的一些更改的問題 有幾種可以使用的變體:

// ...
R.pipe(regex => item => R.test(regex, item), R.filter)
//...

或者

// ...
regex => R.filter(R.test(regex))
//...

但是在最近對 Ramda 進行更改之前,它會很簡單

// ...
R.pipe(R.test, R.filter)
//...

不過,有一件事是 Ramda 努力使參數保持在一個邏輯順序中:那些不太可能改變的先於那些更有可能改變的。 考慮到這一點,我更喜歡這樣的事情:

// getLocalDeps :: RegExp -> [{ source :: { value :: String }}] -> [String]
var getLocalDeps2 =  R.useWith(
  R.call,
  R.pipe(R.unary(R.test), R.filter),
  R.map(R.path(['source', 'value']))
);

localDeps2(localRegex, items); //=> ["./foo"]

那感覺仍然更干凈。 此外,它允許您預定義函數並單獨使用它:

myDeps = localDeps2(localRegex);
myDeps(items); //=> ["./foo"]

這是 Ramda 的一個很好的部分。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM