Home > front end >  How to 'sort' two objects based on number of occurrences of elements in an array field?
How to 'sort' two objects based on number of occurrences of elements in an array field?

Time:06-22

If I have two objects, and they both have two array fields within them, like so:

const list1 = {
  name: 'list-1',
  fruits: ['banana', 'strawberry', 'cherry'],
  vegs: ['lettuce', 'avocado', 'beans']
};

const list2 = {
  name: 'list-2',
  fruits: ['banana', 'apple', 'orange', 'watermelon'],
  vegs: ['potato', 'avocado', 'onion', 'cabbage']
};

And then, I pass in two arrays, one of fruits, and one of vegetables, e.g.:

const fruits = ['banana', 'strawberry'];
const vegetables = ['potato', 'lettuce', 'avocado'];

How can I order the objects, so that has the one with most number of fruits and vegetables (based on the passed in arrays) is on top?

In this case that'd be list1, since it has both "banana" and "strawberry" in fruits, and also has "lettuce" and "avocado" in vegs (i.e. 4 matches in total), whereas list2 only has 2 hits in total.

Not sure if that makes a lot of sense, but what would be the most efficient way to order the two objects based on the arrays?

CodePudding user response:

First, you'll need to define an intersection function - a function that, given two lists, returns a new list containing only the elements found in both lists. There's a very comprehensive answer here if you want to write your own version, or plenty of libraries that you can use to accomplish this (e.g. Ramda or Lodash). You could do this within your sort function, but it's not hard to imagine that you'd need it again in other contexts so it probably makes sense to have a reusable function.

Assuming you've got an implementation of this function available, you can now write a custom compare function that can be used to order objects shaped like list1 and list2 according to the rules you've provided, something like this:

const compareByTotal = (a, b) => {
    const aTotal = intersection(a.fruits, fruits).length   intersection(a.vegs, vegetables).length;
    const bTotal = intersection(b.fruits, fruits).length   intersection(b.vegs, vegetables).length;
 
    return bTotal - aTotal;
}

Finally, you can use this function as a parameter when calling sort to produce a sorted list of these objects:

[list1, list2].sort(compareByTotal);

CodePudding user response:

If I'm understanding your question correctly, first you need to put your objects into their own array and then you can use Array.Prototype.sort: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort

Eg.

const list1 = {
  name: 'list-1',
  fruits: ['banana', 'strawberry', 'cherry'],
  vegs: ['lettuce', 'avocado', 'beans']
};

const list2 = {
  name: 'list-2',
  fruits: ['banana', 'apple', 'orange', 'watermelon'],
  vegs: ['potato', 'avocado', 'onion', 'cabbage']
};

const arrayOfLists = [list1, list2]

arrayOfLists.sort((a, b) => (a.fruits.length   a.vegs.length) < (b.fruits.length   b.vegs.length) )

console.log(arrayOfLists) // Output = [list2, list1] because list 2 has more fruits and vegetables

CodePudding user response:

I think it's fairly easy by looping through them and giving a score to each one then just select a winner that would go like

const list1 = {
  name: 'list-1',
  fruits: ['banana', 'strawberry', 'cherry'],
  vegs: ['lettuce', 'avocado', 'beans']
};

const list2 = {
  name: 'list-2',
  fruits: ['banana', 'apple', 'orange', 'watermelon'],
  vegs: ['potato', 'avocado', 'onion', 'cabbage']
};
const fruits = ['banana', 'strawberry'];
const vegetables = ['potato', 'lettuce', 'avocado'];
const selectAWinner = (fruits,vegetables)=>{
    let list1Score = 0;
    let list2Score = 0;
    fruits.forEach(fruit=>{
        list1.fruits.forEach(fruitFromTheList=>{
            if (fruitFromTheList === fruit)
                list1Score  
        })
    })
    vegetables.forEach(vegetable=>{
        list1.vegs.forEach(vegetableFromTheList=>{
            if (vegetableFromTheList === vegetable)
                list1Score  
        })
    })
      fruits.forEach(fruit=>{
        list2.fruits.forEach(fruitFromTheList=>{
            if (fruitFromTheList === fruit)
                list2Score  
        })
    })
    vegetables.forEach(vegetable=>{
        list2.vegs.forEach(vegetableFromTheList=>{
            if (vegetableFromTheList === vegetable)
                list2Score  
        })
    })
    if (list1Score > list2Score)
    document.write("list 1 wins with score "   list1Score)
    else if (list1Score < list2Score)
    document.write("list 2 wins with score "   list2Score)
    else document.write("it's a tie")
    // or do something else with the results
}
selectAWinner(fruits,vegetables)

  • Related