简体   繁体   中英

Javascript reduce Objects by keys

Is there any underscorejs function (or native/custom js function) that transforms this struct :

(please get a look at the real example @Jsfiddle )

//Simple version, check Jsfiddle for the complete one
var object = {
    "users" : [
        {
            name : "name1"
        },
        {
            name : "name2",
        }
    ]
}

to another object like this :

//Simple version, check Jsfiddle for the complete one
var object2 = {
    users : {
        name : "name1, name2"
    }
}

This makes the same object as your fiddle:

function getType(val){
    if(Object.prototype.toString.call(val) == '[object Array]') return 'array';
    if(val !== null && typeof val === 'object') return 'object';
    return 'other';
}

function deepReduce(object){
    var obj={};
    function travel(object, key, obj){
        if( getType(object) == 'array'){ // if its array, travel
            for(var i=0;i<object.length;i++){
                travel(object[i],key,obj)
            }
        }else if(getType(object)=='object'){ // if its object
            for(var i in object){
                 if(getType(object[i])!='other'){ // if property is object, keep travel
                    if(!obj.hasOwnProperty(i)){
                        obj[i]={};  
                    }
                    travel(object[i],i,obj[i])
                }else{ // else, set property
                    obj[i] =  (obj[i] == undefined ? object[i] : obj[i]+',' + object[i]) ;
                }
            }
        }
    }
    travel(object,null, obj);
    return obj;
}


var reduced=deepReduce(object)
console.log(reduced)

Full fiddle: http://jsfiddle.net/97g5v5tt/

You can do it using map function

object2 = {}
object2.name = object.users.map(function(a){
    return a.name;
}).join(",");

Maybe using reduce? It should be available in ES5.

var users = [{name: 'Joe'}, {name: 'Anna'}];
var names = users.reduce(function(prev, current) {

    return prev.name + ' ' + current.name;
});
console.log(names); // "Joe Anna"

To make this work on your fiddle: http://jsfiddle.net/Lun8kx2k/

You can reduce other keys as well, or write a function that will recursively check keys and reduce them. https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/Reduce

Here is a working solution with a little bit less lines of code:

Object.deepExtend = function xtend(destination, source) {
    for (var property in source) {
        if (source[property] && source[property].constructor && source[property].constructor === Object) {
            destination[property] = destination[property] || {};
            xtend(destination[property], source[property]);
        } else {
            if (!(destination[property] instanceof Array)) {
                destination[property] = destination[property] == null ? source[property] : [destination[property], source[property]].join(",");
            } else {
                destination[property] = destination[property] == null ? source[property] : destination[property].concat(source[property]);
            }
        }
    }
    return destination;
};

Object.deepExtend(object.users[0], object.users[1])

 var object = { "users" : [ { name : "name1", gender : "M", age : "18", rating : {stars : 5, date : "01.01.2014"}, articles : [ { title : "article1", description : "description1" }, { title : "article2", description : "description2" } ] }, { name : "name2", gender : "F", age : "19", rating : {stars : 6, date : "02.01.2014"}, articles : [ { title : "article3", description : "description3" }, { title : "article4", description : "description4" } ] } ] } Object.deepExtend = function xtend(destination, source) { for (var property in source) { if (source[property] && source[property].constructor && source[property].constructor === Object) { destination[property] = destination[property] || {}; xtend(destination[property], source[property]); } else { if (!(destination[property] instanceof Array)) { destination[property] = destination[property] == null ? source[property] : [destination[property], source[property]].join(","); } else { destination[property] = destination[property] == null ? source[property] : destination[property].concat(source[property]); } } } return destination; }; document.body.appendChild(document.createElement('pre')).innerHTML = (JSON.stringify(Object.deepExtend(object.users[0], object.users[1]), undefined,3)); 

This uses lodash (and is only partially complete)... Maybe you could try something like this:

var object2 = { users: {} };

_.each(['name', 'gender', 'age'], function (prop) {
  object2.users[prop] = _.pluck(object.users, prop).join(', ');
});

// returns Object { users: { age: "18, 19", gender: "M, F", name: "name1, name2" }}

DEMO

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM