编辑-使问题更清楚
创建一个搜索,该搜索可以根据项目的标签缩小搜索结果,并仅返回具有指定标签的项目。 示例:['green']将给我所有绿色的项目,包括大,中和小(因为未指定大小),['green','big']仅给我绿色和大的项目。
我遇到了一个场景。为了简化起见,我有以下数据
items: [
{ title: 'prod1', tags: [{ value: 'green' }, { value: 'big' }] },
{ title: 'prod2', tags: [{ value: 'blue' }, { value: 'small' }] },
{ title: 'prod3', tags: [{ value: 'yellow' }, { value: 'medium' }, { value: 'big' }] },
{ title: 'prod4', tags: [{ value: 'green' }, { value: 'big' }, { value: 'medium' }] },
]
我的搜索字段是带有预定义标签的多项选择输入(例如本网站中的标签字段)
该字段的值作为数组输出。如果我选择green
,则输出为['green']
如果我选择green
和big
,则会输出['green','big']
如果我选择标签green
,我应该取回这些结果
{ title: 'prod1', tags: [{ value: 'green' }, { value: 'big' }] },
{ title: 'prod4', tags: [{ value: 'green' }, { value: 'big' }, { value: 'medium' }] },
如果我选择标签green
和medium
,我会得到这些结果,因为prod4是唯一具有绿色和中等标签的
{ title: 'prod4', tags: [{ value: 'green' }, { value: 'big' }, { value: 'medium' }] },
如果我选择green
和big
我应该得到
{ title: 'prod4', tags: [{ value: 'green' }, { value: 'big' }, { value: 'medium' }] },
{ title: 'prod1', tags: [{ value: 'green' }, { value: 'big' }] }
如果未选择任何内容,则输出所有项目
原始问题
I ran into a scenario. To simplify things, i have the following data
items: [
{title: 'one', desc: 'this is one', tags: [{value: 'mytag'},{value: 'one'}]},
{title: 'two', desc: 'this is two', tags: [{value: 'mytag'},{value: two}]},
{title: 'three', desc: 'this is three', tags: [{value: 'mytag'},{value: 'three'},{value: 'common'}]},
{title: 'four', desc: 'this is four', tags: [{value: 'mytag'},{value: 'four'},{value: 'common'}]},
]
我有一个接受标签的搜索输入元素,输入的值是一个数组。输入的值为['tag','two']
我似乎无法弄清楚如何通过标签过滤商品。
如果我通过标签2(['two']
)搜索,我应该会返回
filteredItems: [
{title: 'two', desc: 'this is two', tags: [{value: 'mytag'},{value: two}]},
]
如果我用两个普通(['two','common']
)搜索,我应该会返回
filteredItems: [
{title: 'three', desc: 'this is three', tags: [{value: 'mytag'},{value: 'three'},{value: 'common'}]},
{title: 'four', desc: 'this is four', tags: [{value: 'mytag'},{value: 'four'},{value: 'common'}]},
]
我尝试查看一些示例,发现一些示例仅过滤顶级项目,而不嵌套数组。
谢谢:) 顺便说一下,使用JavaScript可以使用lodash。
我的游乐场JS文件:
const _ = require('lodash')
let items = [
{
name: 'hello',
tags: [
{ value: 1 },
{ value: 2 },
]
},
{
name: 'bye',
tags: [
{ value: 2 },
{ value: 4 },
]
}
]
items.map(item =>{
let test = _.includes(item.tags, 2)
console.log(test)
// returns false, false
})
答案 0 :(得分:3)
(注意:此答案的第一部分与原始问题有关,在其被编辑之前)
您需要更深一层。最终的操场代码将一个对象与2进行比较,但应将一个对象属性与2进行比较。
let test = items.filter(item =>{
return item.tags.some(obj => obj.value === 2)
})
或者,如果要查找的值在另一个属性中:
let test = items.filter(item =>{
return item.tags.some(obj => obj.text === 'two')
})
您的示例数据可以像这样搜索:
function search(items, constraints) {
return items.filter(item =>
constraints.every(constraint =>
item.tags.some(obj => obj.value === constraint)
)
);
}
const items = [
{ title: 'prod1', tags: [{ value: 'green' }, { value: 'big' }] },
{ title: 'prod2', tags: [{ value: 'blue' }, { value: 'small' }] },
{ title: 'prod3', tags: [{ value: 'yellow' }, { value: 'medium' }, { value: 'big' }] },
{ title: 'prod4', tags: [{ value: 'green' }, { value: 'big' }, { value: 'medium' }] },
];
console.log(search(items, ["green", "medium"]));
您需要的逻辑是AND和OR逻辑的组合:对于要匹配给定约束的数组元素,对于每个 ,它应该具有 some 个匹配对象(OR) >在给定约束条件下的值(AND)。
答案 1 :(得分:0)
借助martinoss的post弄清了这一点
解决方案:
使用lodash过滤器功能
let filteredItems = _.filter(items, {tags: [{value: 'green'},{value: 'big'}]}
console.log(filteredItems)
// { title: 'prod1', tags: [{ value: 'green' }, { value: 'big' }] },
// { title: 'prod4', tags: [{ value: 'green' }, { value: 'big' }, { value: 'medium' }] },
这将仅返回具有两个标签(绿色和大)的对象。
我确实必须修改数组并将其转换为对象(我的选择将值输出为['green','big']
我通过以下操作做到了这一点:
let search = ['green', 'big']
search = search.map(searchTag => {
return {value: searchTag}
})
// [{value: 'green'},{value: 'big'}]
如果有一种香草es6的制作方法,我很想看看..现在这对我有用
答案 2 :(得分:0)
下面的代码应该完成您想要的,如果search中的constraints变量为null,undefined,'',[]或未提供,则不进行过滤就返回项目。如果constraints变量是一个字符串,则假设是一个约束,该约束将应用于返回的项目;如果constraints是一个Array,则将应用所有约束。我试图以一种自我解释的方式来命名变量。
var search = (items, constraints) => {
//no constraints supplied, null, undefined, '', or empty array
if ( !constraints || constraints === '' || (Array.isArray(constraints) && constraints.length === 0) ) {
return items;
}
let match = false;
let cons = [];
//constraints is a string with one constraint add it to an array
if (typeof constraints === 'string') {
cons.push(constraints);
}
//if constraints is an array of constraints 1 or more
if (Array.isArray(constraints)) {
cons.concat(constraints);
return items.filter( (item) => {
match = true;
let itemTags = item.tags.map( (tag) => tag.value );
cons.forEach( (constraint) => {
if (constraint === '') return;
match = (itemTags.indexOf(constraint) > -1 && match);
} );
return match;
} );
}
};