Javascript how to return array from map - Stack Overflow

I havethe following Jsonvar myjson = [{"files": [{"domain": "d","

I have the following Json

   var myjson =   [{

            "files": [
                {
                    "domain": "d",
                    "units": [
                        {
                            "key": "key1",
                            "type": "2"

                  },
                        {
                            "key": "key2",
                            "type": "2"
                  },
                        {
                            "key": "key3",
                            "type": "2"
                  }]

            },

                {
                    "domain": "d1",
                    "units": [
                        {
                            "key": "key11",
                            "type": "2"

                  },
                        {
                            "key": "key12",
                            "type": "2"
                  },
                        {
                            "key": "key13",
                            "type": "2"
                  }]

            }]

            },

        {

            "files": [
                {
                    "domain": "d",
                    "units": [
                        {
    ......

I want to create an new array from this Json array. The length of array will be the number of "units" in this Json object.

So I need to extract "units" and add some data from parent objects.

units: [{
        domain: "",
        type: "",
        key: ""
    }, {
        domain: "",
        type: "",
        key: ""
    },
    {
        domain: "",
        type: "",
        key: ""
    }
....
    ];

I guess i can probably do something like this:

var res = [];

myjson.forEach(function(row) {
     row.files.forEach(function(tfile) {
         tfile.units.forEach(function(unit) {

            var testEntity = {
                domain: tfile.domain,
                type : unit.type,
                key: unit.key

            };

            res.push(testEntity);

        });
    });
});

But it is difficult to read and looks not so good. I was thinking to do something like :

var RESULT = myjson.map(function(row) {
     return row.files.map(function(tfile) {
        return  tfile.units.map(function(unit) {

            return {
                domain: tfile.domain,
                type : unit.type,
                key: unit.key

            };



        });
    });
});

But This doesn't work and looks not better . Is there any way to do so it works, maybe in more declarative way. hoped Ramda.js could help.

It there any good approach in general to get data from any Nested json in readable way?

Implementing something like:

nestedjson.findAllOnLastlevel(function(item){

return {
key : item.key,
type: type.key,
domain : item.parent.domain}

});

Or somehow flatten this json so all properties from all parents object are moved to leafs children. myjson.flatten("files.units")

jsbin ,js,console

Many thanks

I have the following Json

   var myjson =   [{

            "files": [
                {
                    "domain": "d",
                    "units": [
                        {
                            "key": "key1",
                            "type": "2"

                  },
                        {
                            "key": "key2",
                            "type": "2"
                  },
                        {
                            "key": "key3",
                            "type": "2"
                  }]

            },

                {
                    "domain": "d1",
                    "units": [
                        {
                            "key": "key11",
                            "type": "2"

                  },
                        {
                            "key": "key12",
                            "type": "2"
                  },
                        {
                            "key": "key13",
                            "type": "2"
                  }]

            }]

            },

        {

            "files": [
                {
                    "domain": "d",
                    "units": [
                        {
    ......

I want to create an new array from this Json array. The length of array will be the number of "units" in this Json object.

So I need to extract "units" and add some data from parent objects.

units: [{
        domain: "",
        type: "",
        key: ""
    }, {
        domain: "",
        type: "",
        key: ""
    },
    {
        domain: "",
        type: "",
        key: ""
    }
....
    ];

I guess i can probably do something like this:

var res = [];

myjson.forEach(function(row) {
     row.files.forEach(function(tfile) {
         tfile.units.forEach(function(unit) {

            var testEntity = {
                domain: tfile.domain,
                type : unit.type,
                key: unit.key

            };

            res.push(testEntity);

        });
    });
});

But it is difficult to read and looks not so good. I was thinking to do something like :

var RESULT = myjson.map(function(row) {
     return row.files.map(function(tfile) {
        return  tfile.units.map(function(unit) {

            return {
                domain: tfile.domain,
                type : unit.type,
                key: unit.key

            };



        });
    });
});

But This doesn't work and looks not better . Is there any way to do so it works, maybe in more declarative way. hoped Ramda.js could help.

It there any good approach in general to get data from any Nested json in readable way?

Implementing something like:

nestedjson.findAllOnLastlevel(function(item){

return {
key : item.key,
type: type.key,
domain : item.parent.domain}

});

Or somehow flatten this json so all properties from all parents object are moved to leafs children. myjson.flatten("files.units")

jsbin http://jsbin./hiqatutino/edit?css,js,console

Many thanks

Share edited Jun 20, 2016 at 10:22 Ant asked Jun 20, 2016 at 10:11 AntAnt 1157 bronze badges 3
  • so you need a working version, which you already have or a good looking version, which could be acplished with ES6 style? – Nina Scholz Commented Jun 20, 2016 at 10:24
  • now I have a working ugly version, but I do a lot of this "nested json operations" Was thinking about a proper approach. Maybe even some general approach. The json I provided is simplified. It could be deeper. Also, new "=>" is not available in my case. – Ant Commented Jun 20, 2016 at 10:39
  • the main problem is to know which property is to iterate. you could give a path with a recursive approach, but at least you need the properties to rebine. – Nina Scholz Commented Jun 20, 2016 at 11:03
Add a ment  | 

4 Answers 4

Reset to default 5

The function you can use here is Ramda's R.chain function rather than R.map. You can think of R.chain as a way of mapping over a list with a function that returns another list and then flattens the resulting list of lists together.

// get a list of all files
const listOfFiles =
  R.chain(R.prop('files'), myjson)

// a function that we can use to add the domain to each unit
const unitsWithDomain =
  (domain, units) => R.map(R.assoc('domain', domain), units)

// take the list of files and add the domain to each of its units
const result =
  R.chain(file => unitsWithDomain(file.domain, file.units), listOfFiles)

If you wanted to take it a step further then you could also use R.pipeK which helps with posing functions together which behave like R.chain between each of the given functions.

// this creates a function that accepts the `myjson` list
// then passes the list of files to the second function
// returning the list of units for each file with the domain attached
const process = pipeK(prop('files'),
                      f => map(assoc('domain', f.domain), f.units))

// giving the `myjson` object produces the same result as above
process(myjson)

Pure JS is very sufficient to produce the result in simple one liners. I wouldn't touch any library just for this job. I have two ways to do it here. First one is a chain of reduce.reduce.map and second one is a chain of reduce.map.map. Here is the code;

var myjson = [{"files":[{"domain":"d","units":[{"key":"key1","type":"2"},{"key":"key2","type":"2"},{"key":"key3","type":"2"}]},{"domain":"d1","units":[{"key":"key11","type":"2"},{"key":"key12","type":"2"},{"key":"key13","type":"2"}]}]},{"files":[{"domain":"e","units":[{"key":"key1","type":"2"},{"key":"key2","type":"2"},{"key":"key3","type":"2"}]},{"domain":"e1","units":[{"key":"key11","type":"2"},{"key":"key12","type":"2"},{"key":"key13","type":"2"}]}]}],
     units = myjson.reduce((p,c) => c.files.reduce((f,s) => f.concat(s.units.map(e => (e.domain = s.domain,e))) ,p) ,[]);
    units2 = myjson.reduce((p,c) => p.concat(...c.files.map(f => f.units.map(e => (e.domain = f.domain,e)))) ,[]);
     console.log(units);
     console.log(units2);

For ES5 patibility i would suggest the reduce.reduce.map chain since there is no need for a spread operator. And replace the arrow functions with their conventional counterparts like the one below;

var myjson = [{"files":[{"domain":"d","units":[{"key":"key1","type":"2"},{"key":"key2","type":"2"},{"key":"key3","type":"2"}]},{"domain":"d1","units":[{"key":"key11","type":"2"},{"key":"key12","type":"2"},{"key":"key13","type":"2"}]}]},{"files":[{"domain":"e","units":[{"key":"key1","type":"2"},{"key":"key2","type":"2"},{"key":"key3","type":"2"}]},{"domain":"e1","units":[{"key":"key11","type":"2"},{"key":"key12","type":"2"},{"key":"key13","type":"2"}]}]}],
     units = myjson.reduce(function(p,c) {
     	                     return c.files.reduce(function(f,s) {
     	                     	                     return f.concat(s.units.map(function(e){
     	                     	                     	                           e.domain = s.domain;
     	                     	                     	                           return e;
     	                     	                     	                         }));
     	                                           },p);
     	                   },[]);
console.log(units);

Something like this should work. .reduce is a good one for these kind of situations.

const allUnits = myjson.reduce((acc, anonObj) => {
   const units = anonObj.files.map(fileObj => {
     return fileObj.units.map(unit => {
       return {...unit, domain: fileObj.domain})
   })
   return [...acc, ...units]
}, [])

Note that this relies on both array spreading and object spreading, which are ES6 features not supported by every platform.

If you can't use ES6, here is an ES5 implementation. Not as pretty, but does the same thing:

var allUnits = myjson.reduce(function (acc, anonObj) {
   const units = anonObj.files.map(function(fileObj) {
     // for each fileObject, return an array of processed unit objects
     // with domain property added from fileObj
     return fileObj.units.map(function(unit) {
       return {
         key: unit.key,
         type: unit.type,
         domain: fileObj.domain
       }
     })
   })
   // for each file array, add unit objects from that array to accumulator array
   return acc.concat(units)
}, [])

Try this

 var myjson = [{

 "files": [{
     "domain": "d",
     "units": [{
       "key": "key1",
       "type": "2"
     }, {
       "key": "key2",
       "type": "2"
     }, {
       "key": "key3",
       "type": "2"
     }]
   },
   {
     "domain": "d1",
     "units": [{
       "key": "key11",
       "type": "2"

     }, {
       "key": "key12",
       "type": "2"
     }, {
       "key": "key13",
       "type": "2"
     }]
   }
 ]
 }];

//first filter out properties exluding units
var result = [];
myjson.forEach(function(obj){
   obj.files.forEach(function(obj2){
     result = result.concat(obj2.units.map(function(unit){
       unit.domain = obj2.domain;
       return unit;
     }));
   });
});

console.log(result);

发布者:admin,转转请注明出处:http://www.yc00.com/questions/1745069238a4609443.html

相关推荐

  • Javascript how to return array from map - Stack Overflow

    I havethe following Jsonvar myjson = [{"files": [{"domain": "d","

    16小时前
    40

发表回复

评论列表(0条)

  • 暂无评论

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信