36

I'm not sure if the title is appropriate for what I am trying to achieve

I am mapping JSON results to an array. Because I need to do this over and over again I would like to put the code into one function.

In the following examples I am repeating myself. I have properties called item.data1, item.data2 and in the second example item.something1, item.something2 ... How can I pass those properties as "general" arguments to the newly created function in order to use them there and not repeat myself to return those maps? The new function should be useable for the two examples below as well as for other cases where the properties could have different names.

service.getData(function(data) {
    var map = {};
    map = $.map(data, function(item, i) {
        var entry = {};

        entry.key = item.data1;
        entry.value = item.data2;

        return entry;
    });
});

service.getSomething(function(data) {
    var map = {};
    map = $.map(data, function(item, i) {
        var entry = {};

        entry.key = item.something1;
        entry.value = item.something2;

        return entry;
    });
});
1
  • return {key:item.something1, value:item.something2} Commented Dec 7, 2012 at 9:38

5 Answers 5

65

use [] with a string to pull out properties from objects dynamically.

var a = { foo: 123 };
a.foo    // 123
a['foo'] // 123

var str = 'foo';
a[str]   // 123

Which means we can refactor your method like so, just pass in the names of the properties you want to read as strings.

var getKeyValueMap = function(data, keyPropName, valuePropName) {
  return $.map(data, function(item, i) {
    return {
      key:   item[keyPropName],
      value: item[valuePropName]
    }
  });
};

service.getData(function(data) {
  return getKeyValueMap(data, 'data1', 'data2');
});

service.getSomething(function(data) {
  return getKeyValueMap(data, 'something1', 'something2');
});
Sign up to request clarification or add additional context in comments.

3 Comments

Thanks Alex. I am starting to think JavaScript came form allies is si powerful
What if the key is one or two levels deep? How do you pass the key by parameter?
You just keep drilling in! obj[propA][propB][propC]
4

this can be done using the [] operators instead of the .-notation just like in this fiddle ive created just for you :D:

    var data = [{
        data1: 'foo',
        data2: 'bar',
        something1: 'sparky',
        something2: 'arf arf!'},
    {
        data1: 'My name is',
        data2: 'What?',
        something1: 'my name is',
        something2: 'Who?!'}
    ];

    function test(data, prop) {
        var d_length = data.length;
        for (var i = 0; i < d_length; i++) {
            alert(data[i][prop]);
        }
    }

    test(data, 'data1');

Comments

1

You will need to pass the item object and a map of item-keys to entry-keys. This could either be two arrays, an array of tuples or something, or an object. Most simple method I could think of is to change the descriptor object into the entry itself:

function mapPropertyNames(source, dest) {
    for (var prop in dest)
        dest[prop] = source[dest[prop]];
    return dest;
}

// and use it like this:

var map = $.map(data, function(item, i) {
    return mapPropertyNames(item, {key:"something1", value:"something2"});
});

Comments

1

Something like

service.getData(function(data) {
    var map = {};
    var varNamePrefix = 'data';
    map = $.map(data, function(item, i) {
        return getProperties(item, varNamePrefix);
    });
});

service.getSomething(function(data) {
    var map = {};
    var varNamePrefix = 'something';
    map = $.map(data, function(item, i) {
        return getProperties(item, varNamePrefix);
    });
});

function getProperties(item, varNamePrefix) {
    var ret = {};
    ret.key = item[varNamePrefix + '1'];
    ret.value = item[varNamePrefix + '2'];
    return ret;
}

May help?

Basically, you could use a function that takes a property prefix and uses it to form the actual property names to get from items.

Comments

-1

try this:

service.getData(function(data, props) {// props is a property object
    var map = {};
    map = $.map(data, function(item, i) {
        var entry = {};

        for (var key in props) {
            entry[key] = item[key]
        }

        return entry;
    });
});

or use a property array

service.getData(function(data, props) {// props is like ['data1', 'data2']
    var map = {};
    map = $.map(data, function(item, i) {
        var entry = {};

        for (var j = 0, k = props.length; j < k; j++) {
            entry[props[j]] = item[props[j]]
        }

        return entry;
    });
});

4 Comments

What exactly do you mean by "property object"?
@Bergi an object contain what properties needed, eg: {data1: 1, data2: 1}
This does not work as "key" != "data1" - the OP wants the properties to be renamed. Btw, your array answer makes much more sense...
the key point is pass the properties to the function as a parameter and you can give different value every time, what type of the parameter is not important, choose one you think convenient

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.