根据包含的数组内容过滤对象数组。 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”,所以我希望在ae的情况下是一个空列表,除非他的意思是别的 我在第二个项目的技术人员中添加了一个“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

无法根据另一个对象数组过滤对象数组

Angular2使用管道基于对象数组过滤对象数组

使用 vanilla JS 删除 ES5 及更低版本数组中重复数字的最快方法是啥?

根据另一个 id 数组对对象数组进行排序