是数组中的值还是对象 Ramda 中的字符串

Is value in array or string inside object Ramda

这里有点奇怪,我正在解析查询字符串,有时它们作为字符串返回,有时作为字符串数组返回(取决于是否存在一个与多个)。

我想查询key下是否存在value,需要在数据为空或null的情况下工作

# we have access to both the key and value
const key = 'locations'
const value = 'London'

数据的形状如下:

# does 'London' exist under `locations`?
{
  locations: 'London',
  skills: ['1', '2'],
}

数据的形状也可能如下所示:

{
  locations: ['London', 'Reading'],
  skills: '1',
}

我考虑过使用 pathSatisfiespathEqcontains,但没有成功。我似乎对值可以包含在字符串或数组中这一事实感到困惑。

如评论中所述,使用Array.isArray()查看属性是否包含数组,如果包含则使用数组方法,否则直接比较值

const key = 'locations',
  value = 'London',
  data = {
    locations: 'London',
    skills: ['1', '2'],
  },
  data2 = {
    locations: ['London', 'Reading'],
    skills: '1',
  }

const hasValue = (data, key, value) => {
  const testVal = data[key];
  return Array.isArray(testVal) ? testVal.includes(value) : testVal === value;
}

// string version
console.log(hasValue(data, key, value));
   // array version
console.log(hasValue(data2, key, value))

如果密钥还没有,我会使用透镜将其转换为阵列。然后你可以简单地使用 propSatisfiesincludes:

const toArr = unless(is(Array), of);

const check = (key, value) =>
  pipe(
    over(lensProp(key), toArr),
    propSatisfies(includes(value), key));

console.log(
  check('locations', 'London')({locations: ['London', 'Reading']})
);

console.log(
  check('locations', 'London')({locations: 'London'})
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/ramda/0.26.1/ramda.min.js"></script>
<script>const {unless, is, of, pipe, over, lensProp, propSatisfies, includes} = R;</script>


编辑: 实际上这可以简化为 includes 同时处理字符串和数组:

const check = (key, value) => where({[key]: includes(value)})

console.log(
  check('locations', 'London')({locations: 'London'})
);

console.log(
  check('locations', 'London')({locations: ['London', 'Reading']})
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/ramda/0.26.1/ramda.min.js"></script>
<script>const {where, includes} = R;</script>

这个小函数应该可以帮助您。

function hasValue(obj, key, value) {
    if (!obj) return false;
    let prop = obj[key];
    if (!prop) return false;
    if (Array.isArray(prop))
        return prop.indexOf(value) >= 0;
    return prop === value;
}