如何在ramda中链接多个“或”或“与”语句,并保留短路评估?

问题描述

我想根据用户定义的文本过滤帖子数组。每个帖子都有一个id一个text属性,应该对其进行搜索。如果搜索文本为空字符串,则所有帖子显然都应显示-无需检查其他谓词是否解析为true。目前,我正在执行以下操作:

const hasText = R.curry((text,post) => R.reduce(R.or,false,[
    R.equals("",text),R.includes(text,post.text),post.id.toString())
]))

const posts = [{id: 1,text: "a"},{id: 2,text: "b"},{id: 3,text: "c"}]

console.log(R.filter(hasText("b"),posts));
<script src="https://cdnjs.cloudflare.com/ajax/libs/ramda/0.27.1/ramda.min.js"></script>

这里的问题是,即使没有必要,所有谓词都需要预先评估。

是否可以使用ramda以更实用的方式获得与使用普通||相同的效果

解决方法

如果文本为空字符串,则根本不需要过滤数组。要检查任何谓词是否真实,可以使用R.any:

S1 = {
    'device_type': 'cisco_ios','ip': '192.168.0.56','username': 'admin','password': 'admin'
    }

S2= {
    'device_type': 'cisco_ios','ip': '192.168.0.57','password': 'admin'
    }

all_devices = [S1,S2]


for devices in all_devices:
    print("\nLogging into the switch...")
    net_connect = ConnectHandler(**devices)
    net_connect.enable()
    cmd = ["show vlan brief","\n","show ip interface brief"]
    for show in cmd:
        output=net_connect.send_command(show)
        y = output

print(y)
const { curry,pipe,prop,toString,includes,filter,anyPass,isEmpty } = R

// check if prop includes text
const propIncludes = curry((key,text) => pipe(prop(key),includes(text)))

// filter an array of posts,and check if any of the prop contains the text
const hasText = curry((text,posts) => filter(anyPass([
  propIncludes('text',text),propIncludes('id',]))(posts))

// skips filtering if text is empty
const checkText = curry((text,posts) => isEmpty(text) ? posts : hasText(text,posts))

const posts = [{id: 1,text: "a"},{id: 2,text: "b"},{id: 3,text: "c"}]

const result = checkText('b',posts)

console.log(result);

,

您可以按照与其他答案的R.propSatisfies函数类似的方式使用内置的propIncludes函数:

const textContains = curry(
  (srch,value) => pipe(toString,includes(srch))(value)
)

const postHasText = curry(
  (text,post) => anyPass([
        propSatisfies(textContains(text),'text'),propSatisfies(textContains(text),'id')
  ])(post)
)

const postsWithText = curry(
  (text,posts) => filter(postHasText(text),posts)
)

或者,如下面的示例所示,您可以创建一个中间帮助器方法propsContain,然后postHasText会更简单,并且您也可以将propsContain重用于其他事情

const { curry,props,any,isEmpty } = R

const textContains = curry(
  (srch,includes(srch))(value)
)

const propsContain = curry(
  (srch,propList,entity) => pipe(props(propList),any(textContains(srch)))(entity)
)

const postHasText = propsContain(R.__,['id','text'],R.__)

const searchPosts = curry(
  (qry,posts) => isEmpty(qry) ? posts : filter(postHasText(qry),posts)
)

const posts = [{id: "a",text: "foo"},text: "box"},text: "bat"}]
const results = searchPosts('a',posts)
console.log(results)
<script src="https://cdnjs.cloudflare.com/ajax/libs/ramda/0.27.1/ramda.min.js"></script>