简体   繁体   中英

How to use array includes and check an object against a property of an object

I have an array classTopics where an object looks like this:

{
  questions:2,
  id:49,
  topic:{
    edited: null
    id: 1
    name: "Topic name"
    status: "ACTIVE"
    topicCode:"02"
  }
}

And I also have an array allTopics where the objects are the same as topic property in the example above:

 {
    edited: null
    id: 1
    name: "Topic name"
    status: "ACTIVE"
    topicCode:"02"
  }

In the select field I would like to filter all the topics that are the same as a property topic in the objects of the classTopics array. So, something like this:

 <AutoCompleteSelect
   options={allTopics.filter(topic => !classTopics.includes(topic)).map(({name}) => ({value: name, label: name}))}
 />

But, that is not working since it is checking the objects as a whole. How can I do something similar where I could check it against the property on the object?

Basically what I am trying to achieve is this in a nicer way:

const filteredTopics = allTopics
                        .filter(topic => 
                          (classTopics.findIndex(classTopic => classTopic.topic.id === topic.id)) === -1);

You can find the working example here .

Compare by entire object (each property)

You can use some to check if the topic is inside the classTopics array, and use every with Object.entries to check that each property is the same inside the topics array:

 const classTopics = [{ questions: 2, id: 49, topic: { edited: null, id: 1, name: "Topic name", status: "ACTIVE", topicCode: "02" }}] const allTopics = [{ edited: null, id: 1, name: "Topic name", status: "ACTIVE", topicCode: "02" }] const filterTopics = (a, c) => { return a.filter(topic => c .some(c => Object.entries(c.topic) .every(([k,v]) => topic[k] === v) ) ) } console.log(filterTopics(allTopics, classTopics)) 

Compare by ID

As suggested in the comments, checking the entire object is overkill, the purpose of an ID is to identify an object uniquely - using ID's makes for a much more efficient solution:

 const classTopics = [{ questions: 2, id: 49, topic: { edited: null, id: 1, name: "Topic name", status: "ACTIVE", topicCode: "02" }}] const allTopics = [{ edited: null, id: 1, name: "Topic name", status: "ACTIVE", topicCode: "02" }] const filterTopics = (a, c) => a.filter(topic => c.some(t => t.topic.id === topic.id)) console.log(filterTopics(allTopics, classTopics)) 

I will prefer to do this filtering in js file instead of html for simplicity. Also I am using here lodash js lib to reduce code size.

 const classTopics = [{ questions: 2, id: 49, topic: { edited: null, id: 1, name: "Topic name", status: "ACTIVE", topicCode: "02" }}] const allTopics = [{ edited: null, id: 1, name: "Topic name", status: "ACTIVE", topicCode: "02" }] const topicsToshow = _.unionWith(allTopics,classTopics,(cT,aT)=> aT.id===cT.topic.id) console.log(topicsToshow) 
 <script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.14/lodash.min.js"></script> 

You can compare just by topic ID, name or other property instead of whole topic objects:

allTopics
  .filter(topic => !classTopics.map(t => t.id).includes(topic.id))
  .map(topic => ({value: topic.name, label: topic.name}))

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM