这是一个普遍存在的问题,但是我的特定用例是基于包含真/假设置的对象构建一个“友好的”过滤器名称。
以下是这些设置对象之一的示例
var settings = {
includeMen: true,
includeWomen: false,
includeDependents: true,
}
业余解决方案将是一大堆if
语句,例如
if(settings.includeMen && settings.includeWomen && settings.includeDependents){
return "All People"
}
if(settings.includeMen && !settings.includeWomen && settings.includeDependents){
return "Men and Children"
}
if(settings.includeMen && settings.includeWomen && !settings.includeDependents){
return "Men and Women"
}
...
还有没有那么业余的想法吗? (如果有帮助,项目将使用Lodash)
答案 0 :(得分:4)
const {includeMen, includeWomen, includeDependents} = settings;
const result = [];
if(includeMen) result.push("Men");
if(includeWomen) result.push("Women");
if(includeDependents) result.push("Children");
if(result.length === 3)
return "All people";
if(!result.length)
return "No one";
return result.join(" and ");
如果您想为每种情况提供自定义输出,则可以进行一些有趣的位移:
const {includeMen, includeWomen, includeDependents} = settings;
return [
"No one",
"Children",
"Women",
"Children and Women",
"Men",
"Men and Children",
"Men and Women",
"All people"
][+includeDependents + (includeWomen << 1) + (includeMen << 2)];
(免责声明:如果您这样做,您的队友会恨您:))
答案 1 :(得分:1)
您可以通过多种方式来执行此操作, 可能我会在运行时转换对象键,然后生成字符串:
var settings = {
includeMen: true,
includeWomen: false,
includeDependents: true,
}
var trueFields = Object.entries(settings).reduce((ac, [k, v]) =>
v ?
[...ac, k.replace(/^include/,'')] :
ac
,[])
var str = !trueFields.length ?
'nobody ...' :
trueFields.join(' and ')
console.log(str)
答案 2 :(得分:0)
我在注释中提到的一个很好的例子,它涉及使用Mozilla docs的按位运算符将多个booleans
与二进制进行往返
自动创建蒙版
您可以从一组遮罩中创建多个遮罩 布尔值,如下所示:
function createMask() {
var nMask = 0,
nFlag = 0,
nLen = arguments.length > 32 ? 32 : arguments.length;
for (nFlag; nFlag < nLen; nMask |= arguments[nFlag] << nFlag++);
return nMask;
}
var mask1 = createMask(true, true, false, true); // 11, i.e.: 1011
var mask2 = createMask(false, false, true); // 4, i.e.: 0100
var mask3 = createMask(true); // 1, i.e.: 0001
// etc.
alert(mask1); // prints 11, i.e.: 1011
反向算法:掩码中的布尔数组
如果您想通过遮罩创建
Array
中的Booleans
,则可以使用以下代码:function arrayFromMask(nMask) { // nMask must be between -2147483648 and 2147483647 if (nMask > 0x7fffffff || nMask < -0x80000000) { throw new TypeError('arrayFromMask - out of range'); } for (var nShifted = nMask, aFromMask = []; nShifted; aFromMask.push(Boolean(nShifted & 1)), nShifted >>>= 1); return aFromMask; } var array1 = arrayFromMask(11); var array2 = arrayFromMask(4); var array3 = arrayFromMask(1); alert('[' + array1.join(', ') + ']'); // prints "[true, true, false, true]", i.e.: 11, i.e.: 1011
答案 3 :(得分:0)
您得到的各种各样的答案表明,没有一种事实上的正确方法可以实现这一目标。我的方法是创建一个易于阅读和编辑的过滤器名称定义数组,并且可以在其中搜索匹配的名称。
我喜欢这种方法的原因是,当使用新名称添加新的过滤器时,无需编辑执行搜索的逻辑。只需在过滤器名称列表中添加一个新定义即可。
这1)减少了引入错误的机会,2)将复杂性封装在易于测试且很少更改的功能内,并且3)对团队成员而言很明显。
const SETTING_PREFIX = "include";
const removeInclude = k => k.substr(SETTING_PREFIX.length, k.length);
const isTrue = x => !!x;
const isFalse = x => !x;
const getFilteredProps = (filter, predicate) => {
return Object.keys(filter).filter(k =>
predicate(filter[k])
)
}
const getFilterName = filter => {
const trueFilterProps = getFilteredProps(filter, isTrue).map(removeInclude);
const falseFilterProps = getFilteredProps(filter, isFalse).map(removeInclude);;
const filterNameDefinition = filterNames.find(definition =>
trueFilterProps.every(key =>
definition[0].includes(key)
) &&
falseFilterProps.every(key =>
!definition[0].includes(key)
)
);
if (!filterNameDefinition) {
return "Unnamed filter";
}
return filterNameDefinition[0].join(" and ");
}
const settings = {
includeMen: false,
includeWomen: true,
includeDependents: true
};
const filterNames = [
[["Men", "Women", "Dependents"], "All People"],
[["Men", "Dependents"], "Men and Children"]
];
console.log(getFilterName(settings))