Bill
Bill

Reputation: 67

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.

Upvotes: 5

Views: 150

Answers (4)

Koushik Chatterjee
Koushik Chatterjee

Reputation: 4175

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>

Upvotes: 1

31piy
31piy

Reputation: 23859

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

Upvotes: 1

Niladri Basu
Niladri Basu

Reputation: 10614

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>

Upvotes: 1

Orelsanpls
Orelsanpls

Reputation: 23515

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

Upvotes: 1

Related Questions