Search code examples
arraysknockout.jsuniqueko.observablearray

Get observableArray of unique values from another obseravableArray


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


Solution

  • 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