根据包含的数组内容过滤对象数组。 Vanilla JS,lodash,其他一些与反应相关的技术?
Posted
技术标签:
【中文标题】根据包含的数组内容过滤对象数组。 Vanilla JS,lodash,其他一些与反应相关的技术?【英文标题】:filtering an array of objects based on a contained arrays contents. Vanilla JS, lodash, some other react releated technology? 【发布时间】:2018-02-16 01:45:11 【问题描述】:所以我正在制作一个反应应用程序,并且我有一个使用特定技术的项目列表。我希望用户能够通过某些复选框(可能)说我正在寻找使用“a”、“b”和“c”技术的项目,并且项目列表将自动更新。我应该为此使用香草javascript(对对象数组进行排序)还是有更简单的方法来做到这一点?
如果这应该通过 vanilla javascript 完成,请有人给我一些指导。能够成功地搜索一种“技术”,但无法完全完成搜索多种技术。
示例数据如下。
const projects = [
name: 'projecta',
technologies: ['a', 'b', 'f'],
link: 'www.example.com'
,
name: 'projectb',
technologies: ['c', 'd', 'e'],
link: 'www.example.com'
,
name: 'projectc',
technologies: ['a', 'b', 'c', 'd', 'e'],
link: 'www.example.com'
];
【问题讨论】:
【参考方案1】:您可以在过滤时使用解构并检查所有想要的技术。
const
projects = [ name: 'projecta', technologies: ['a', 'b', 'f'], link: 'www.example.com' , name: 'projectb', technologies: ['c', 'd', 'e'], link: 'www.example.com' , name: 'projectc', technologies: ['a', 'b', 'c', 'd', 'e'], link: 'www.example.com' ],
search = ['c', 'e'],
result = projects.filter(( technologies ) =>
search.every(s => technologies.includes(s)));
console.log(result);
.as-console-wrapper max-height: 100% !important; top: 0;
【讨论】:
不错的解决方案@Nina,但请注意并非所有浏览器都支持.includes()。 @chsdk,解构,两者都没有,但 op 使用const
,所以它是 ES6。
是的,也许你是对的,但我只是为其他人提到了它;)
@NinaScholz wo (⊙⊙)(☉_☉)(⊙⊙) w nice【参考方案2】:
如果您有多个复选框,您将获得一个数组,其中包含所有选定复选框的值。 过滤基于一个或多个值的数组将像这样工作:
const projects = [
name: 'projecta',
technologies: ['a', 'b', 'f'],
link: 'www.example.com'
,
name: 'projectb',
technologies: ['c', 'd', 'e'],
link: 'www.example.com'
,
name: 'projectc',
technologies: ['a', 'b', 'c', 'd', 'e'],
link: 'www.example.com'
];
const search = ['c', 'e'];
const result = projects.filter(project =>
return search.every(s => project.technologies.includes(s));
);
// or
const result2 = projects.filter(project =>
return !search.some(s => project.technologies.indexOf(s) === -1);
);
console.log(result);
console.log(result2);
【讨论】:
但他提到关系是“AND”,所以我希望在a
和e
的情况下是一个空列表,除非他的意思是别的
我在第二个项目的技术人员中添加了一个“a”,我会修复它并使用另一个搜索来测试。【参考方案3】:
是的,你可以只使用 vanilla JS 来做到这一点,你可以从 Array 的内置方法中获益。
您可以结合使用 .filter()
和 .some()
方法根据指定的技术列表过滤您的数组。
这应该是你的代码:
const techs = ['a', 'c'];
var filtered = projects.filter(function(p)
return !techs.some(function(t)
return p.technologies.indexOf(t) === -1;
);
);
演示:
const projects = [
name: 'projecta',
technologies: ['a', 'b', 'f'],
link: 'www.example.com'
,
name: 'projectb',
technologies: ['c', 'd', 'e'],
link: 'www.example.com'
,
name: 'projectc',
technologies: ['a', 'b', 'c', 'd', 'e'],
link: 'www.example.com'
];
const techs = ['a', 'c'];
var filtered = projects.filter(function(p)
return !techs.some(function(t)
return p.technologies.indexOf(t) === -1;
);
);
console.log(filtered);
说明:
我们使用filter()
方法循环遍历数组过滤其元素,并在其回调函数中使用.some()
方法测试迭代项目technologies
以确保它们都在给定的技术列表中.
【讨论】:
感谢您的解决方案...和解释!【参考方案4】:假设您将选定的技术存储在一个数组中,您可以简单地使用 filter()
循环遍历每个项目并返回那些至少具有一项技术的项目。
在下面的 sn-p 中,我们使用 filter
遍历每个项目,这意味着我们创建一个包含满足回调条件的项目的数组。
回调对当前项目的每个技术进行另一个过滤,并返回过滤后数组的长度。如果当前项目的任何技术都与您的选择不匹配,则数组长度为零,这是一个虚假值,整个对象将不会返回到新数组中。
例如:
let selectedTechs = ['a', 'b']; //selected techs
const projects = [
name: 'projecta',
technologies: ['a', 'b', 'f'],
link: 'www.example.com'
,
name: 'projectb',
technologies: ['c', 'd', 'e'],
link: 'www.example.com'
,
name: 'projectc',
technologies: ['a', 'b', 'c', 'd', 'e'],
link: 'www.example.com'
];
let arr = projects.filter(
(item) => item.technologies.filter((x) => selectedTechs.includes(x)).length
);
console.log(arr); //returns the 1st and 3rd project object.
还有一个 React 演示:
class MyApp extends React.Component
constructor()
super();
this.state =
technologies: ['a', 'b', 'c', 'd', 'e', 'f'],
checkedTechs: [],
projects: [
name: 'projecta',
technologies: ['a', 'b', 'f'],
link: 'www.example.com'
,
name: 'projectb',
technologies: ['c', 'd', 'e'],
link: 'www.example.com'
,
name: 'projectc',
technologies: ['a', 'b', 'c', 'd', 'e'],
link: 'www.example.com'
]
;
checkTech = (name) =>
let arr = this.state.checkedTechs.slice();
if(arr.includes(name))
arr.splice(arr.indexOf(name), 1);
else
arr.push(name);
this.setState(checkedTechs: arr);
render()
let technologies, checkedTechs, projects = this.state;
return(
<div>
<div>
technologies.map(
(item) => <label key=item>item<input value=checkedTechs.indexOf(item)>-1 onChange=this.checkTech.bind(this, item) type="checkbox" /></label>
)
</div>
<ul>
this.state.projects.filter(
(item) => item.technologies.filter((x) => checkedTechs.includes(x)).length
).map(
(item) => <li key=item.name>item.name</li>
)
</ul>
</div>
);
ReactDOM.render(<MyApp />, document.getElementById("app"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.js"></script>
<div id="app"></div>
以上是显示包含所选技术的项目。如果您想选择具有完全所选技术的项目,请将过滤器逻辑替换为:
(item) => item.technologies.join(',') === checkedTechs.sort().join(',')
【讨论】:
不错的解决方案,但请注意并非所有浏览器都支持.includes()。 @chsdk,好点子。这适用于支持 ES6 或使用 babel-polyfill 的浏览器。 我非常喜欢这个,谢谢!超级干净的代码。对于这个项目,所有浏览器都不支持 .includes() 可能并不重要。 @D.Wall,很高兴你发现它有用!我为 React 实现添加了示例代码。另外,如果这有帮助,请考虑将其标记为“已接受”。祝你好运。【参考方案5】:您可以为此使用 javascript。比如说,在每次点击checkbox
时,您的复选框值都会保存在选择中,然后您可以获得这样的对象,
const projects = [
name: 'projecta',
technologies: ['a', 'b', 'f'],
link: 'www.example.com'
,
name: 'projectb',
technologies: ['c', 'd', 'e'],
link: 'www.example.com'
,
name: 'projectc',
technologies: ['a', 'b', 'c', 'd', 'e'],
link: 'www.example.com'
];
var choice = 'e';
var res= projects.filter((x)=>
if(x.technologies.indexOf(choice) !== -1)
return x;
);
console.log(res);
【讨论】:
感谢您的回复。这将只允许搜索一项包含的技术,对吗?只是'e'。我在下面提出了一个解决方案,但我不确定这是不是最好的方法。【参考方案6】:我发现了一些有用的东西。最好的解决方案?
const checkFor = ['a', 'b'];
const winners = projects.filter(project =>
return checkFor.every(function(val)
return project.technologies.indexOf(val) !== -1;
);
);
console.log('winners: ', winners);
【讨论】:
哇一堆现在可以使用的解决方案。感谢所有回复的人。将解决所有这些问题。以上是关于根据包含的数组内容过滤对象数组。 Vanilla JS,lodash,其他一些与反应相关的技术?的主要内容,如果未能解决你的问题,请参考以下文章
javascript [Find Place]用于根据值#vanilla #script检索给定数字在数组中的位置的索引的脚本
将动态数据从数组对象插入到引导模式中 - vanilla javascript