Pregunta

I have an array of objects, shown below. The first segment of code is within a loop where multiple objects of 'Item' are created and pushed onto the array.

Example of the problem is available here: http://jsfiddle.net/X6VML/
Notice how changing the value inside a textbox displays a duplicate item.

 // class
 var Item = function(label, value) {
    this.Label = label;
    this.Value = value;
 };

 var obj = new Item("My Label", "My Value");

 // adds object onto array
 itemArray.push(obj);

The problem I have is that the array can contain duplicate objects which I need to filter out before rending the list of objects into a table, shown below:

  for (var i = 0; i < itemArray.length; i++) {
      $('.MyTable').append("<tr><td>" + itemArray[i].Label + "</td><td>" + itemArray[i].Value + "</td></tr>");
  }

I can identify whether it's a duplicate with the Value being the same. How can I filter the list of objects based on whether the Value already exists in the array?

Many thanks

¿Fue útil?

Solución 2

A simple solution would be:

var temp = [];
$.each(itemArray, function(index, obj){
    var found = false;
    $.each(temp, function(tempI, tempObj){
        if(tempObj.Value == obj.Value){
            found = true;
            return false;
        }
    });

    if(!found){
        temp.push(obj);
    }
});

itemArray = temp;
console.log(itemArray);

The above is simply iterating over each object in the array, and pushing it to the temp array if it's not already there, finally it overwrites itemArray with temp.


Have you considered eliminating duplicates at the point of adding to the array? Something like this:

function UniqueItemList(){
    var items = [];

    this.push = function(item){
        for(var i=0; i<items.length; i++){
            if(items[i].Value == item.Value){
                return;
            }
        }
        items.push(item);
    };

    this.getList = function(){
        return items;
    }
}

var myList = new UniqueItemList();

myList.push(new Item('label1', 'value1'));
myList.push(new Item('label2', 'value2'));
myList.push(new Item('label1', 'value1'));
myList.push(new Item('label1', 'value1'));

console.log(myList.getList());

If you try to push a duplicate item, it will be rejected.

Demo - here it is integrated into your code.

Otros consejos

Just don't add duplicate item in array:

var item = new Item("My Label", "My Value1");

if(!$.grep(itemArray, function(obj) { return obj.Value == item.Value; }).length)
  itemArray.push(item);

If there is already an object with Value "My Value1" in itemArray, just don't add it.

This code would do. Modify the itemArray before forming the HTML.

var arr = {};
for ( var i=0; i < itemArray.length; i++ )
    arr[itemArray[i].Value] = itemArray[i];
itemArray = new Array();
for ( key in arr )
    itemArray.push(arr[key]);

I've got this handy utility function:

function uniq(ary, key) {
    var seen = {};
    return ary.filter(function(elem) {
        var k = (key || String)(elem);
        return seen[k] === 1 ? 0 : (seen[k] = 1);
    })
}

where key is a function that fetches the comparison key from an element.

Applied to your use case:

uniqueItems = uniq(itemArray, function(item) { return item.Value })
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top