0

Lets say I have this object here:

var items = [
    {name:"Foo"},
    {name:"Bar"},
    {name:"foo"},
    {name:"bar"},
    {name:"foobar"},
    {name:"barfoo"}
];

Since it only has one item in each object, I want to just return a list of them.

I tried this:

var getSingle = function(rows){
    var items = [];
    //This should only return one column
    for (var i = 0; i < rows.length; i++) {
        var r = rows[i];
        var c = 0;
        for (var n in r) {
            if(c == 0)
                items.push(r[n]);
            c += 1;
        }
    }
    return items;
}

But it doesn't seem to work. Any thoughts?

PS. name could be anything.

2
  • So you want this? items = ['Foo', 'Bar', 'foo', ...]. Check out map. Commented Mar 8, 2013 at 3:24
  • Correct, without knowing that the first object is name Commented Mar 8, 2013 at 3:28

5 Answers 5

2

I used a different approach than the others, because I make two assumptions:

1/ you do not know the name of the key, but there is only one key for every item 2/ the key can be different on every item I will give you a second option, with the second assumption as: 2/ all item have only one key but that's the same for all of them

First Options :

var items = [
        {name:"Foo"},
        {name:"Bar"},
        {name:"foo"},
        {name:"bar"},
        {name:"foobar"},
        {name:"barfoo"}
    ];

// object keys very simple shim
Object.keys = Object.keys || function(o) {  
    var result = [];  
    for(var name in o) {  
        if (o.hasOwnProperty(name))  
          result.push(name);  
    }  
    return result;  
};

// function to get the value of every first keys in an object
// just remember that saying "first key" does not make real sense
// but we begin with the assumption that there IS ONLY ONE KEY FOR EVERY ITEM
// and this key is unknown
function getFirstKeysValues(items) {
    var i = 0, len = items.length, item = null, key = null, res = [];
    for(i = 0; i < len; i++) {
        item = items[i];
        key = Object.keys(item).shift();
        res.push(item[key]);
    }

    return res;
}

console.log(getFirstKeysValues(items)); //["Foo", "Bar", "foo", "bar", "foobar", "barfoo"]

Second options will use a map, because we believe that every child possess the same key (I wouldn't use this one, because I do not like .map that much - compatibility):

var items = [
        {name:"Foo"},
        {name:"Bar"},
        {name:"foo"},
        {name:"bar"},
        {name:"foobar"},
        {name:"barfoo"}
    ];

// object keys very simple shim
Object.keys = Object.keys || function(o) {  
    var result = [];  
    for(var name in o) {  
        if (o.hasOwnProperty(name))  
          result.push(name);  
    }  
    return result;  
};

// function to get the value of every first keys in an object
// just remember that saying "first key" does not make real sense
// but we begin with the asumption that there IS ONLY ONE KEY FOR EVERY ITEM
// and this key is unknown but the same for every child
function getFirstKeysValues(items) {
    var key = items.length > 0 ? Object.keys(items[0]).shift() : null;

    items = items.map(function (item) {
        return item[key];
    });

    return items;
}

console.log(getFirstKeysValues(items));
Sign up to request clarification or add additional context in comments.

1 Comment

Perfect. This is exactly what I wanted.
2

This is usually accomplished using the map method, see the documentation here.

   var justNamesArray = items.map(function(elem) { return elem.name});

The documenation page also includes a useful shim, that is a way to include it in your code to support older browsers.

Accompanying your request in the edit, if you would just like to get those that contain this property there is a nifty filter method.

 var valuesWithNamePropert= items.filter(function(elem) { return elem.hasOwnProperty("name")});

You can chain the two to get

var justNamesWhereContains = items.filter(function(elem) { return elem.hasOwnProperty("name")}).
                                  .map(function(elem) { return elem.name});

This approach (mapping and filtering), is very common in languages that support first order functions like JavaScript.

Some libraries such as underscore.js also offer a method that does this directly, for example in underscore that method is called pluck.

EDIT: after you specific that the property can change between objects in the array you can use something like:

var justReducedArray = items.map(function(elem) { for(i in elem){ return elem[i]}});

6 Comments

How about without knowing that the object contains name, it could contain anything
@SmartLemon See my edit, also, if the objects do not contain a name property it would just return undefined as JavaScript returns undefined when accessing properties that do not exist (no exceptions)
Forget name I mean, if the object was {eman:"Foo"} then I still want it
That is not what you originally specified. Note that for... in loops have NO guarantee of the order of iteration. Your code might get different columns in different iterations, I would not recommend using it in production code.
"since it only has one item in each object, I want to just return a list of them." is where I specified it xD
|
1

your var items = [] is shadowing your items parameter which already contains data. Just by seeing your code I thought that maybe your parameter should be called rows

2 Comments

I think @eburgos is saying that your function accepts a parameter items, which you immediately overwrite with an empty array.
Yes, that's what I was saying. I just created this fiddle jsfiddle.net/DVD8n with the renamed function and it worked
1

If you're in a world >= IE9, Object.keys() will do the trick. It's not terribly useful for the Array of Objects, but it will help for the iteration of the Array (you would use Array.forEach to iterate the array proper, but then you would use the Object.keys(ob)[0] approach to get the value of the first property on the object. For example:

var someArr = [{ prop1: '1' },{ prop2: '2' },{ prop3: '3' }];
var vals = [];
someArr.forEach( function(obj) {
    var firstKey = Object.keys(obj)[0]; 
    vals.push(obj[firstKey]);
});
//vals now == ['1','2','3']

Obviously this isn't null safe, but it should get you an array of the values of the first property of each object in the original array. Say that 3 times fast. This also decouples any dependency on the name of the first property--if the name of the first property is important, then it's a trivial change to the forEach iteration.

Comments

1

You can override the Array.toString method for items, so using String(items) or alert(items) or items+='' will all return the string you want-

var items = [{name:"Foo"}, {name:"Bar"},{name:"foo"},
{name:"bar"},{name:"foobar"},{name:"barfoo"}];

items.toString= function(delim){
    delim=delim || ', ';
    return this.map(function(itm){
        return itm.name;
    }).join(delim);
}

String(items)

/* returned value: (String) Foo, Bar, foo, bar, foobar, barfoo */

instead of the default string-'[object Object],[object Object],[object Object],[object Object],[object Object],[object Object]'

1 Comment

You have given me an idea.

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.