简体   繁体   中英

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.

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); 

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], })), ]; }, [])); 

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> 

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> 

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