最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - filtering an array of objects based on a contained arrays contents. Vanilla JS, lodash, some other react releated t

programmeradmin1浏览0评论

So i'm making a react app and I have a list of projects that use specific technologies. I want the user to be able to be able to say i'm looking for a project that uses 'a', 'b', and 'c' technologies via some checkboxes (maybe) and the list of projects will automatically update. Should i just be using vanilla javascript for this (to sort through an array of objects) or is there an easier way to do it?

If this should be done via vanilla javascript, can someone give me a little direction please. was able to do this successfully search for just one 'technology' but couldn't quite get it done searching for multiple technologies.

Example data to be below.

const projects = [{
  name: 'projecta',
  technologies: ['a', 'b', 'f'],
  link: 'www.example'
},
{
  name: 'projectb',
  technologies: ['c', 'd', 'e'],
  link: 'www.example'
},
{
  name: 'projectc',
  technologies: ['a', 'b', 'c', 'd', 'e'],
  link: 'www.example'
}];

So i'm making a react app and I have a list of projects that use specific technologies. I want the user to be able to be able to say i'm looking for a project that uses 'a', 'b', and 'c' technologies via some checkboxes (maybe) and the list of projects will automatically update. Should i just be using vanilla javascript for this (to sort through an array of objects) or is there an easier way to do it?

If this should be done via vanilla javascript, can someone give me a little direction please. was able to do this successfully search for just one 'technology' but couldn't quite get it done searching for multiple technologies.

Example data to be below.

const projects = [{
  name: 'projecta',
  technologies: ['a', 'b', 'f'],
  link: 'www.example.'
},
{
  name: 'projectb',
  technologies: ['c', 'd', 'e'],
  link: 'www.example.'
},
{
  name: 'projectc',
  technologies: ['a', 'b', 'c', 'd', 'e'],
  link: 'www.example.'
}];
Share Improve this question edited Sep 7, 2017 at 11:26 Kalamarico 5,69622 gold badges56 silver badges73 bronze badges asked Sep 7, 2017 at 10:43 D. WallD. Wall 771 gold badge1 silver badge17 bronze badges
Add a ment  | 

6 Answers 6

Reset to default 3

You could use a destructuring while filtering with checking all wanted technologies.

const
    projects = [{ name: 'projecta', technologies: ['a', 'b', 'f'], link: 'www.example.' }, { name: 'projectb', technologies: ['c', 'd', 'e'], link: 'www.example.' }, { name: 'projectc', technologies: ['a', 'b', 'c', 'd', 'e'], link: 'www.example.' }],
    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; }

If you have multiple checkboxes you will get an array which contains the value of all selected checkboxes. Filter the array based one or multiple values will work like this:

const projects = [
    {
        name: 'projecta',
        technologies: ['a', 'b', 'f'],
        link: 'www.example.'
    },
    {
        name: 'projectb',
        technologies: ['c', 'd', 'e'],
        link: 'www.example.'
    },
    {
        name: 'projectc',
        technologies: ['a', 'b', 'c', 'd', 'e'],
        link: 'www.example.'
    }
];

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);

Yes you can do it using only vanilla JS, you can profit from Array's buil-in methods to do it.

You can use a bination of .filter() and .some() methods to filter your array based on the specified technologies list.

This is how should be your code:

const techs = ['a', 'c'];
var filtered = projects.filter(function(p){
    return !techs.some(function(t){
        return p.technologies.indexOf(t) === -1;
    });
});

Demo:

const projects = [
    {
        name: 'projecta',
        technologies: ['a', 'b', 'f'],
        link: 'www.example.'
    },
    {
        name: 'projectb',
        technologies: ['c', 'd', 'e'],
        link: 'www.example.'
    },
    {
        name: 'projectc',
        technologies: ['a', 'b', 'c', 'd', 'e'],
        link: 'www.example.'
    }
];

const techs = ['a', 'c'];
var filtered = projects.filter(function(p){
    return !techs.some(function(t){
        return p.technologies.indexOf(t) === -1;
    });
});

console.log(filtered);

Explanation:

We use filter() method to loop over the array filter its elements and in its callback function we use .some() method to test over the iterated project technologies to make sure they're all among of the given technologies list.

Assuming you store the selected technologies in an array, you could simply loop through each project with filter() and return those that have at least one of the techs.

In the snippet below we iterate through each project with filter, meaning we create an array with items that satisfy the criteria in the callback.

The callback does another filter for each tech of the current project, and returns the length of the filtered array. If no tech of the current project matches your selection, the array length is zero which is a falsy value and the whole object won't be returned to the new array.


For example:

let selectedTechs = ['a', 'b'];  //selected techs
const projects = [
    {
        name: 'projecta',
        technologies: ['a', 'b', 'f'],
        link: 'www.example.'
    },
    {
        name: 'projectb',
        technologies: ['c', 'd', 'e'],
        link: 'www.example.'
    },
    {
        name: 'projectc',
        technologies: ['a', 'b', 'c', 'd', 'e'],
        link: 'www.example.'
    }
];

let arr = projects.filter(
  (item) => item.technologies.filter((x) => selectedTechs.includes(x)).length
);

console.log(arr); //returns the 1st and 3rd project object.


and a demo in 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.'
        },
        {
            name: 'projectb',
            technologies: ['c', 'd', 'e'],
            link: 'www.example.'
        },
        {
            name: 'projectc',
            technologies: ['a', 'b', 'c', 'd', 'e'],
            link: 'www.example.'
        }
      ]
    };
  }
  
  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./ajax/libs/react/15.1.0/react.js"></script>
<script src="https://cdnjs.cloudflare./ajax/libs/react/15.1.0/react-dom.js"></script>
<div id="app"></div>

The above is to show project that include the selected techs. If you want to select projects that have exactly the selected techs, replace the filter logic with:

(item) => item.technologies.join(',') === checkedTechs.sort().join(',')

You can use javascript for this. Say, in each click of checkbox your checkbox value is saved in choice then you can get the objects like this,

const projects = [
    {
        name: 'projecta',
        technologies: ['a', 'b', 'f'],
        link: 'www.example.'
    },
    {
        name: 'projectb',
        technologies: ['c', 'd', 'e'],
        link: 'www.example.'
    },
    {
        name: 'projectc',
        technologies: ['a', 'b', 'c', 'd', 'e'],
        link: 'www.example.'
    }
];

var choice = 'e';

var res= projects.filter((x)=>{
   if(x.technologies.indexOf(choice) !== -1){
      return x;
   }
});

console.log(res);

I've found something that works. best solution?

const checkFor = ['a', 'b'];
const winners = projects.filter(project => {

            return checkFor.every(function(val) {
                return project.technologies.indexOf(val) !== -1;
            });
        });

        console.log('winners: ', winners);

与本文相关的文章

发布评论

评论列表(0)

  1. 暂无评论