Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

use underscore or lodash convert one JSON structure to another

I have a problem trying to convert current JSON structure to another

var data = [
  {
    "url": "asset/01.flv",
    "pic": "asset/01.jpg"
  },
  {
    "url": "asset/02.flv",
    "pic": "asset/02.jpg"
  },
  {
    "url": "asset/03.flv",
    "pic": "asset/03.jpg"
  },
  {
    "url": "asset/04.flv|asset/05.flv|asset/06.flv|asset/07.flv|asset/08.flv",
    "pic": "asset/04.jpg|asset/05.jpg|asset/06.jpg|asset/07.jpg|asset/08.jpg"
  },
  {
    "url": "asset/09.flv|asset/10.flv",
    "pic": "asset/09.jpg|asset/10.jpg"
  }
]

I want to convert data to an output structure like this.
Here's the target with just the result I want to achieve.

var data = [
  {
    "url": "asset/01.flv",
    "pic": "asset/01.jpg"
  },
  {
    "url": "asset/02.flv",
    "pic": "asset/02.jpg"
  },
  {
    "url": "asset/03.flv",
    "pic": "asset/03.jpg"
  },
  {
    "url": "asset/04.flv",
    "pic": "asset/04.jpg"
  },
  {
    "url": "asset/05.flv",
    "pic": "asset/05.jpg"
  },
  {
    "url": "asset/06.flv",
    "pic": "asset/06.jpg"
  },
  {
    "url": "asset/07.flv",
    "pic": "asset/07.jpg"
  },
  {
    "url": "asset/08.flv",
    "pic": "asset/08.jpg"
  },
  {
    "url": "asset/09.flv",
    "pic": "asset/09.jpg"
  },
  {
    "url": "asset/10.flv",
    "pic": "asset/10.jpg"
  }
]

It is diffcult for me, could someone help me in this matter? I've tried for several hours. Using lodash or underscore or plain JS is ok. Thanks in advance.

like image 553
Bill Avatar asked Jul 27 '18 09:07

Bill


4 Answers

You can do it with the use of Array#reduce. The idea is to loop over the array and check if the url and pic has | in their values.

If so, split the value and push all items to the result. If not, push the url and pic as it is.

var data = [{"url":"asset/01.flv","pic":"asset/01.jpg"},{"url":"asset/02.flv","pic":"asset/02.jpg"},{"url":"asset/03.flv","pic":"asset/03.jpg"},{"url":"asset/04.flv|asset/05.flv|asset/06.flv|asset/07.flv|asset/08.flv","pic":"asset/04.jpg|asset/05.jpg|asset/06.jpg|asset/07.jpg|asset/08.jpg"},{"url":"asset/09.flv|asset/10.flv","pic":"asset/09.jpg|asset/10.jpg"}];

var result = data.reduce((r, {url, pic}) => {
  if (url.includes('|') && pic.includes('|')) {
    var urls = url.split('|');
    var pics = pic.split('|');
    
    urls.forEach((u, i) => {
      r.push({url: u, pic: pics[i]});
    });
  } else {
    r.push({url, pic})
  }
  
  return r;
}, []);

console.log(result);
like image 138
31piy Avatar answered Oct 13 '22 00:10

31piy


You can use of an Array.reduce to do the manipulation yourself.

const arr = [{
    "url": "asset/01.flv",
    "pic": "asset/01.jpg"
  },
  {
    "url": "asset/02.flv",
    "pic": "asset/02.jpg"
  },
  {
    "url": "asset/03.flv",
    "pic": "asset/03.jpg"
  },
  {
    "url": "asset/04.flv|asset/05.flv|asset/06.flv|asset/07.flv|asset/08.flv",
    "pic": "asset/04.jpg|asset/05.jpg|asset/06.jpg|asset/07.jpg|asset/08.jpg"
  },
  {
    "url": "asset/09.flv|asset/10.flv",
    "pic": "asset/09.jpg|asset/10.jpg"
  }
];

console.log(arr.reduce((tmp, {
  pic,
  url,
}) => {
  const urlSplit = url.split('|');

  return [
    ...tmp,

    ...pic.split('|').map((x, xi) => ({
      pic: x,
      url: urlSplit[xi],
    })),
  ];
}, []));
like image 39
Orelsanpls Avatar answered Oct 13 '22 01:10

Orelsanpls


IMHO, you can do something like this using Array#reduce():

var data = [{"url":"asset/01.flv","pic":"asset/01.jpg"},{"url":"asset/02.flv","pic":"asset/02.jpg"},{"url":"asset/03.flv","pic":"asset/03.jpg"},{"url":"asset/04.flv|asset/05.flv|asset/06.flv|asset/07.flv|asset/08.flv","pic":"asset/04.jpg|asset/05.jpg|asset/06.jpg|asset/07.jpg|asset/08.jpg"},{"url":"asset/09.flv|asset/10.flv","pic":"asset/09.jpg|asset/10.jpg"}];

var parsedData = data.reduce((accumulator, e) => {
  e['url'].split('|').forEach((ele, i) => {
    accumulator.push({"url":ele, "pic": e['pic'].split('|')[i]})
  })
  return accumulator;
}, [])

console.log(parsedData);

Same solution using Underscore.js's _.zip() function.

var data = [{"url":"asset/01.flv","pic":"asset/01.jpg"},{"url":"asset/02.flv","pic":"asset/02.jpg"},{"url":"asset/03.flv","pic":"asset/03.jpg"},{"url":"asset/04.flv|asset/05.flv|asset/06.flv|asset/07.flv|asset/08.flv","pic":"asset/04.jpg|asset/05.jpg|asset/06.jpg|asset/07.jpg|asset/08.jpg"},{"url":"asset/09.flv|asset/10.flv","pic":"asset/09.jpg|asset/10.jpg"}];

var parsedData = data.reduce((accumulator, e) => {
  return accumulator.concat(...(_.zip(e['url'].split('|'), e['pic']
             .split('|'))
             .map(([url, pic]) => ({url, pic}))))
}, []);

console.log(parsedData)
<script src="https://underscorejs.org/underscore-min.js"></script>
like image 34
BlackBeard Avatar answered Oct 12 '22 23:10

BlackBeard


How about simply use a flatmap with zipWith??

const sortedData = _.flatMap(data, obj =>
    _.zipWith(
        obj.url.split("|"),
        obj.pic.split("|"),
        (url, pic) => ({url, pic})
    )
);

var data = [
  {
    "url": "asset/01.flv",
    "pic": "asset/01.jpg"
  },
  {
    "url": "asset/02.flv",
    "pic": "asset/02.jpg"
  },
  {
    "url": "asset/03.flv",
    "pic": "asset/03.jpg"
  },
  {
    "url": "asset/04.flv|asset/05.flv|asset/06.flv|asset/07.flv|asset/08.flv",
    "pic": "asset/04.jpg|asset/05.jpg|asset/06.jpg|asset/07.jpg|asset/08.jpg"
  },
  {
    "url": "asset/09.flv|asset/10.flv",
    "pic": "asset/09.jpg|asset/10.jpg"
  }
]

var res = _.flatMap(data, o=>_.zipWith(o.url.split("|"), o.pic.split("|"), (url, pic) => ({url, pic})));

console.log(res);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.10/lodash.min.js"></script>
like image 42
Koushik Chatterjee Avatar answered Oct 12 '22 23:10

Koushik Chatterjee