0

I have tried this code to find if some object already exists in Array, but, it is not working:

function lote(pnIdLote,psNmLote, pnIdQuadro){ 
    this.idlote = pnIdLote; 
    this.nmlote = psNmLote;
    this.idquadro = pnIdQuadro;
}

Array.prototype.contains = function(obj){
    var i = this.length;
    while(i--){
        console.log(i);
        if (this[i] == obj) return true;
    }
    return false;
};

My code:

$(data).each(function(index){
 if(this.idlote!=""){
    loLote = new lote(this.idlote, this.nmlote, this.quadro);
    if(!laLote.contains(loLote)){
        laLote.push(loLote);
    }
 }
});
console.log(laLote);

The array appears this way:

[
lote
idlote: "2"
idquadro: "1"
nmlote: "Lote 1"
__proto__: lote
, 
lote
idlote: "2"
idquadro: "1"
nmlote: "Lote 1"
__proto__: lote
, 
lote
idlote: "2"
idquadro: "1"
nmlote: "Lote 1"
__proto__: lote
]

And I'd like an array with only one element, like this:

[
lote
idlote: "2"
idquadro: "1"
nmlote: "Lote 1"
__proto__: lote
]

Where do I fix my code?

Thanks, Luciano

Luciano Borges
  • 817
  • 3
  • 12
  • 31

2 Answers2

1

When a and b are objects in JavaScript, a == b or a === b is only true if a and b point to the same instance.

Example:

var a = [], b = [], c = a;
alert(a == b); // False
alert(a == c); // True

For your specific comparison method, I recommend creating a custom array constructor, to not pollute the Array object:

function lote() {} // Your lote constructor

var customArray = function() {
    return Array.apply(this, arguments);
}
customArray.prototype = new Array;
customArray.prototype.contains = function(obj) {
    var i = this.length;
    // Not designed for non-"lote" instances, return null
    if (!(obj instanceof lote)) return null;

    while (i--) {
        var current = this[i];
        if (current.idlote === obj.idlote &&
            current.nmlote === obj.nmlote &&
            current.idquadro === obj.idquadrio) return true;
    }
    return false;
}

Instead of hard-coding the property names, you can also loop through the Object's properties, using Object.keys():

customArray.prototype.contains = function(obj) {
    var i = this.length;
    // Not designed for non-"lote" instances, return null
    if (!(obj instanceof lote)) return null;

    var keys = Object.keys(obj), keysLen = keys.length;
    // Labeled loop
    loop: while (i--) {
        var current = this[i];
        var len = keysLen, key;
        for (len--) {
            key = keys[len];
            if (current[key] !== current[key]) {
                len = -1;
                continue loop; //Not equal, go to the next item in the outer loop
            }
        }
        return true; // At this point, every property was equal.
    }
    return false;
}

Note that the shown method depends is based on the properties of the given obj. If it's not a valid lote object, the function returns null. Object.keys retrieves all properties of the given obj.

Rob W
  • 341,306
  • 83
  • 791
  • 678
  • Oh, by the way: The `laLote` array has to be created using `var laLote = new customArray();`. – Rob W Jan 25 '12 at 14:32
0

I think you should change the "contains" method to use Object.equals function, and you could use the code of

Array.prototype.contains = function(obj){
    var i = this.length;
    while(i--){
        console.log(i);
        if(this[i].equals(obj)) return true;
    }
    return false;
};

Object.prototype.equals = function(x){
  var p;
  for(p in this) {
      if(typeof(x[p])=='undefined') {return false;}
  }

  for(p in this) {
      if (this[p]) {
          switch(typeof(this[p])) {
              case 'object':
                  if (!this[p].equals(x[p])) { return false; } break;
              case 'function':
                  if (typeof(x[p])=='undefined' ||
                      (p != 'equals' && this[p].toString() != x[p].toString()))
                      return false;
                  break;
              default:
                  if (this[p] != x[p]) { return false; }
          }
      } else {
          if (x[p])
              return false;
      }
  }

  for(p in x) {
      if(typeof(this[p])=='undefined') {return false;}
  }

  return true;
}

Code of object comparison extracted from Object comparison in JavaScript

Community
  • 1
  • 1
Xavi Ivars
  • 634
  • 8
  • 22
  • Extending the array's prototype is already tricky. Now you're also suggesting to override the `Object`'s prototype? – Rob W Jan 25 '12 at 13:57
  • It's the nearest solution to your question I could find. Of course, you could replacte the "equals" function to a standalone function with two parameters `equals(a,b)` and replace all `this` with `a` inside the function, and all `x` with `b`. But the solution would be the same: you need to deeply compare all object members – Xavi Ivars Jan 25 '12 at 17:06