Confusing problem using methods for clean-up code

I’m currently having trouble figuring out why both methods such as “addToSet()” and “removeFromSet()” isn’t working as expected. The situation here is that the methods doesn’t distinguish between “male” and “female” when called inside the “gender” scope. Basically, the “obj” keeps the “female” gender. When the “obj” identifier is used instead, it works like below:

var People_names = ['male 04/09/1982 (mother Daily Stacy): Doctor Brian the 2nd, John',
                    'male 20/02/1972 (mother Maria Doe): Doctor William, Billy',
                    'female 14/12/1986 (mother Stephanie Lopez): Doctor Hermes, Lisa',
                    'female 20/09/1904 (mother Stasha White): Doctor Bill, Ashley',
                    'male 10/07/1975 (mother Daily Brown): Doctor Brian the 2nd, Garth'];

var startsWith = function (start, end) {
    return start.slice(start, end.length) === end;
};

var addToSet = function (set, values) {
    for (var x = 0; x < values.length; x += 1) {
        set[values[x]] = true;
    }
}

var removeFromSet = function () {
    for (var x = 0; x < values.length; x += 1) {
        delete set[values[x]];
    }
};

var extractNames = function (arr) {

    var len = arr.length,
        names = [],
        list;

    for (var x = 0; x < arr.length; x += 1) {

        list = arr[x];
        names[x] = list.slice(list.indexOf(',') + 2);

    }

    return names;
};

var gender = function (index, obj) {
    obj = obj || {};

    var x,
        len = index.length,
        extract = extractNames(index);

    for (x = 0; x < len; x += 1) {
        if (startsWith(index[x], 'male')) {
            obj[extract[x]] = true;
        }
    }
    return obj;
};

gender(People_names);

Both methods are called in the scope, which doesn’t separate both genders:

var gender = function (index, obj) {
    obj = obj || {};

    var x,
        len = index.length,
        extract = extractNames(index);

    for (x = 0; x < len; x += 1) {
        if (startsWith(index[x], 'male')) {
            addToSet(obj, extract);
        }
        else if(startsWith(index[x], 'female')) {
            removeFromSet(obj, extract);
        }
    }
    return obj;
};

My code is similar to the original code, which came from “Eloquent JavaScript” by the way.

Can anyone help me with this problem?

Thanks

Hi shurns,

What exactly is it that you’re trying to achieve? The addToSet function is just adding all the values from one array/object to another. You’re passing in extract, which is an array of all the names in the original list, so that’s what you end up with as the result.

Hi, fretburner

Sorry for the misunderstanding. What I’m trying to figure out is why is it that the “addToSet()” function passes all of it’s names onto the object. I was expecting the same results as this statement:

obj[extract[x]] = true;

The above statement only has the male gender stored in the object as expected, since I used an conditional operator. This is something I was trying to achieve with the addToSet() function, but instead, both genders are stored in the object, which I didn’t want.

Is there away around this?

Thanks!

Well, here’s the relevant section of code from the gender function:

var x,
    len = index.length,
    extract = extractNames(index);

for (x = 0; x < len; x += 1) {
    if (startsWith(index[x], 'male')) {
        addToSet(obj, extract);
    }
}

On the third line, extract gets assigned an array of all the names from People_names. Then, when the loop runs you’re checking each item in People_names for the gender, and if the person is male, then you’re calling addToSet and passing in obj (which is empty the first time around) and extract, which is the array of all names.

var addToSet = function (set, values) {
    for (var x = 0; x < values.length; x += 1) {
        set[values[x]] = true;
    }
}

Add to set it then looping over the array, and adding the value (the persons name) to the empty object that was passed in. As the loop in gender runs again, addToSet is called again and the values on the object are overwritten. So the end result is an object with all the names from the original list, male and female.

Are you actually trying to filter the original array, so that only the male individuals remain? Or you’re just trying a different way of getting the same result as the original code (ie. a list of the male names)?

Thanks for the help, fretburner

Yes, I was trying to filter out the original array so the male individuals remain by using the addToSet, but instead it adds both genders.

Apologies, let me re-phrase that, I was just trying to get the same result as the original code by using the “addToSet” method (which was a different result).

Well, the smallest change you could make to achieve that would be to pass the name for the current item into addToSet (wrapped in an array, as that’s what the function expects):

for (x = 0; x < len; x += 1) {
    if (startsWith(index[x], 'male')) {
        addToSet(obj, [extract[x]]);
    }
}

but it’s the same amount of code as doing set[values[x]] = true; so I don’t see any advantage.

Interesting. I never thought of it that way to pass an array in the method.

Thanks.