Get observableArray of unique values from another obseravableArray

623 Views Asked by At

I'm having data like:

    { mealName: "sandwich", price: 0 },
    { mealName: "lobster", price: 34.95 },
    { mealName: "whole zebra", price: 290 },
    { mealName: "whole zebra", price: 290 },
    { mealName: "sandwich", price: 290 },
    { mealName: "whole zebra", price: 290 }

And I want to get observableArray like:

{ mealName: "sandwich"},
{ mealName: "whole zebra"},
{ mealName: "lobster"}

I've tried to reproduce it in jsFiddle, but something is wrong

2

There are 2 best solutions below

0
Wayne Ellery On BEST ANSWER

unique doesn't have to be an observable array as the availableMeals is not an observable array, but since you asked I used a computed.

First I sort the array using a custom sort function. I used concat to create a copy as I didn't want to modify the order of the original array. I then loop through the sorted array and remove any duplicates:

self.unique = ko.computed(function() {
     var sortedItems = self.availableMeals.concat().sort(function(left, right) { return left.mealName == right.mealName ? 0 : (left.mealName < right.mealName ? -1 : 1) });

     var meal;

     for (var i = 0; i < sortedItems.length; i++) {                 
         if (!meal || meal != sortedItems[i].mealName) {
             meal = sortedItems[i].mealName;
         }
         else {
             sortedItems.splice(i, 1);
             i--;
         }
     }

     return sortedItems;
});     

jsfiddle

0
Retsam On
var uniqueMeals = ko.computed(function () {
    var uniqueMealNames = mealData().reduce(function(uniqueMeals, meal) {
        if(uniqueMeals.indexOf(meal.mealName) === -1) {
            uniqueMeals.push(meal.mealName);
        }
        return uniqueMeals;
    }, []);

    return uniqueMealNames.map(function(mealName) {
        return {mealName: mealName};
    });
});

Some suggestions: it's probably be better to store the unique values in an array of strings, not objects, i.e. ["sandwich", "whole zebra", "lobster"]. If so, you can drop the last line from my above code.

Also, you might consider looking into the lodash library. With lodash, this would be:

var uniqueMeals = ko.computed(function () {
    return _.unique(_.pluck(mealData, "mealName"));
})