-2

I have implemented a set datatype in javascript based in a generic object type, like this:

function createSetFromList(list) {
    var set = { };
    for (var i = 0; i < list.length; i++)
        set[list[i]] = true;
    return set;
}

Now I can easily check whether a given value belongs to the set:

var users = createSetFromList(my_users);
if (user in users) allow_operation = true;

The problem that I have is that I would like to check if my set is empty, like this:

if ("users is empty" or user in users) allow_operation = true;

But I have no idea how to check if the set is empty. I have tried with:

if (users == { } || user in users) allow_operation = true;

But apparently the first part of the logical expression is never true.

I guess it has to do with the fact that when users is empty, it is still initialized as an object, without any set elements, and an object is never equal to another object?

Is there any workaround to check for emptiness for my set implementation?

EDIT: I have tried out Malvolio's suggestion, and something strange is going on. I have modified it a bit to see what is happening:

function showProperties(v) {
    for (x in v) {
        if (v.hasOwnProperty(x)) {
            $.log(x + " belongs");
        } else {
            $.log(x + " does not belong");
        }
    } 
}

When running this:

showProperties(myset);

I always get only one line, regardless with which data my set has been initialized:

undefined belongs
blueFast
  • 41,341
  • 63
  • 198
  • 344
  • possible duplicate of [How do I test for an empty Javascript object from JSON?](http://stackoverflow.com/questions/679915/how-do-i-test-for-an-empty-javascript-object-from-json) – Lightness Races in Orbit Nov 01 '11 at 08:24
  • Note that object property names must be strings or numbers, so you must overload `toString` to return a unique string for any object that may be added to a set. – outis Nov 01 '11 at 08:35
  • Numbers are actually toString'd also, ie when used in arrays – meandmycode Nov 01 '11 at 10:57
  • The behavior of `showProperties` you ask about in the edit is a different issue, and thus deserves a different question. It may be related to the issue I mention in my first comment, namely that generic objects aren't suitable for property names, since names must be strings. – outis Nov 03 '11 at 02:33

2 Answers2

2

Best I have is

var isEmptyObject = function(v) { 
   for (x in v) {
     if (v.hasOwnProperty(x)) {
          return false;
     }
   } 
   return true;
};
Michael Lorton
  • 43,060
  • 26
  • 103
  • 144
  • 1
    In one line: `!Object.keys(mySet).length`. – katspaugh Nov 01 '11 at 08:46
  • @katspaugh Object.keys dont supported in IE8 and older – Andrew D. Nov 01 '11 at 08:49
  • @Andrew D., there are so many shims for less advanced environments that you really shouldn't deprive yourself of ES5 goodness. – katspaugh Nov 01 '11 at 08:55
  • @Malvolio: Excuse my ignorance, but how would you use that `isEmptyObject` function? I am JS beginner, and that construct looks very strange to me. First, you are walking with a `for` loop through the properties *and* then checking whether they are object properties. Isn't that true by definition? Second, you are defining `isEmptyObject` as `var`. Why not directly as function? – blueFast Nov 01 '11 at 09:12
  • @gonvaled You're looping through the properties, indeed. If there's no property, the body of the loop won't ever be reached, and the function moves onward to `return true` (is empty). Otherwise, the function returns false (not empty). – Rob W Nov 01 '11 at 09:41
  • @gonvaled - it's `hasOwnProperty`, not `hasProperty` (I don't think `hasProperty` even exists). If some idiot puts something in Object.prototype, every invocation of the `in` operator will include that key in the loop but `hasOwnProperty` will properly eliminate it. The difference between creating a named function and assigning an anonymous function to a variable is subtle and controversial. I think realistically it boils down to a matter of taste and mine runs that way. – Michael Lorton Nov 01 '11 at 09:51
1

You can use Array for your task.

Or if you need to use special kind of operations on set you can define set as:

function SetOfValues(list) {
    if(!(this instanceof SetOfValues))
       return arguments.length===1?new SetOfValues(list):new SetOfValues;
    if(arguments.length===1)for(var i=0;i<list.length;i++)this[list[i]]=true;
}
SetOfValues.prototype.in=function(item) {
  return this.hasOwnProperty(item);
}
SetOfValues.prototype.empty=function() {
  for(var p in this)if(this.hasOwnProperty(p))return false;
  return true;
}

and then create and use set as:

var users = new SetOfValues(my_users);
// or with help of SetOfValues definition simply:
// var users = SetOfValues(my_users);
if(users.in(user)) allow_operation = true;
if(users.empty()||users.in(user)) allow_operation = true;
Andrew D.
  • 8,130
  • 3
  • 21
  • 23
  • @gonvaled. Is a _strict equal_ comparison operator. Read more about javascript operators in MDN: https://developer.mozilla.org/en/JavaScript/Reference/Operators – Andrew D. Nov 01 '11 at 09:47