我有一个场景,我需要从一个对象中获取字符串的第一次出现,但前提是匹配出现在一个预定义的路径中。
{ id: 'I60ODI', description: 'some random description' }
{ foo: 'bar', description: { color: 'green', text: 'some description within text' } }
当提供上面两个对象中的任何一个时,我希望解决方案返回some random description
或some description within text
,前提是这两个可能的路径是obj.description
和 obj.description.text
。将来可能还需要添加新路径,因此添加它们需要很容易。
这是我目前已经实现的解决方案,但对我来说它似乎不是最优的。
// require the ramda library
const R = require('ramda');
// is the provided value a string?
const isString = R.ifElse(R.compose(R.equals('string'), (val) => typeof val), R.identity, R.always(false));
const addStringCheck = t => R.compose(isString, t);
// the possible paths to take (subject to scale)
const possiblePaths = [
R.path(['description']),
R.path(['description', 'text'])
];
// add the string check to each of the potential paths
const mappedPaths = R.map((x) => addStringCheck(x), possiblePaths);
// select the first occurrence of a string
const extractString = R.either(...mappedPaths);
// two test objects
const firstObject = { description: 'some random description' };
const secondObject = { description: { text: 'some description within text' } };
const thirdObject = { foo: 'bar' };
console.log(extractString(firstObject)); // 'some random description'
console.log(extractString(secondObject)); // 'some description within text'
console.log(extractString(thirdObject)); // false
如果经验丰富的函数式程序员可以为我提供一些替代实现方法,我将不胜感激。谢谢。
最佳答案
这会起作用,而且我认为它更干净:
const extract = curry((defaultVal, paths, obj) => pipe(
find(pipe(path(__, obj), is(String))),
ifElse(is(Array), path(__, obj), always(defaultVal))
)(paths))
const paths = [['description'], ['description', 'text']]
extract(false, paths, firstObject) //=> "some random description"
extract(false, paths, secondObject) //=> "some description within text"
extract(false, paths, thirdObject) //=> false
我个人会在 ''
中找到比在 false
中更好的默认值,但那是你的决定。
这避免了映射所有路径,在找到第一个路径时停止。它还使用 Ramda 的 is
将复杂的 isString
替换为 R.is(String)
。柯里化(Currying)允许您提供第一个或前两个参数来创建更有用的函数。
您可以在 Ramda REPL 中看到实际效果.
关于javascript - 从一系列可能的路径中获取字符串,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46619331/