javascript - Using map and filter on multiple arrays in an object - Stack Overflow

Using Wikipedia's API I got an object which looks like that:obj = {["string", Array[10],

Using Wikipedia's API I got an object which looks like that:

obj = {["string", Array[10], Array[10], Array[10]]}

The first array contains titles, second is descriptions and third is links.

Some of the descriptions may be empty ("").

Example -

I would like to bine all three arrays into one array as follow:

[{title: obj[1][0], desc: obj[2][0], link: obj[3][0]}, ... , {title: array[1][9], desc: obj[2][0], link: obj[3][0]}]

But only bining if description is not empty - obj[2][i] !== ""

I managed to do it using for loop and if:

var arr = [];
for (var i = 0; i < data[1].length; i++) {
  if (data[2][i] !== '') {
    arr.push({title: data[1][i], desc:data[2][i], link: data[3][i]});
  }
}

Is there a way of achieving the same in a more elegant way using javascript's high order function? such as map and filter (maybe reduce?)

Thanks

EDIT:

The way I did it in the end was:

var resp = ["Football",
  ['Football', 'Soccer'],
  ['FootballDescription', 'SoccerDescription'],
  ['', '']
];

// Mimic python's zip behavior -> assume arrays are of equal size
function zip(arrays) {
  return arrays[0].map(function(_, i){
    return arrays.map(function(array){
        return array[i];
    });
  });
}

// 1. Throw away the first string, e.g. "Football"
resp.shift();

// 2. Use zip to make an array of intersected arrays, i.e
// [
//   ['Football', 'FootballDescription', ''],
//   ['Soccer', 'SoccerDescription', '']
// ]
// and then use map to make each array into a nicely named object
var objects = zip(resp).map(function(x) {
    return ({ name: x[0], desc: x[1], link: x[2] });
});

console.log(objects);
/*
Output:
[ { name: 'Football',
    description: 'FootballDescription',
    link: '' },
  { name: 'Soccer',
    description: 'SoccerDescription',
    link: '' } ]
*/   

Using Wikipedia's API I got an object which looks like that:

obj = {["string", Array[10], Array[10], Array[10]]}

The first array contains titles, second is descriptions and third is links.

Some of the descriptions may be empty ("").

Example -

I would like to bine all three arrays into one array as follow:

[{title: obj[1][0], desc: obj[2][0], link: obj[3][0]}, ... , {title: array[1][9], desc: obj[2][0], link: obj[3][0]}]

But only bining if description is not empty - obj[2][i] !== ""

I managed to do it using for loop and if:

var arr = [];
for (var i = 0; i < data[1].length; i++) {
  if (data[2][i] !== '') {
    arr.push({title: data[1][i], desc:data[2][i], link: data[3][i]});
  }
}

Is there a way of achieving the same in a more elegant way using javascript's high order function? such as map and filter (maybe reduce?)

Thanks

EDIT:

The way I did it in the end was:

var resp = ["Football",
  ['Football', 'Soccer'],
  ['FootballDescription', 'SoccerDescription'],
  ['http://football.', 'http://soccer.']
];

// Mimic python's zip behavior -> assume arrays are of equal size
function zip(arrays) {
  return arrays[0].map(function(_, i){
    return arrays.map(function(array){
        return array[i];
    });
  });
}

// 1. Throw away the first string, e.g. "Football"
resp.shift();

// 2. Use zip to make an array of intersected arrays, i.e
// [
//   ['Football', 'FootballDescription', 'http://football.'],
//   ['Soccer', 'SoccerDescription', 'http://soccer.']
// ]
// and then use map to make each array into a nicely named object
var objects = zip(resp).map(function(x) {
    return ({ name: x[0], desc: x[1], link: x[2] });
});

console.log(objects);
/*
Output:
[ { name: 'Football',
    description: 'FootballDescription',
    link: 'http://football.' },
  { name: 'Soccer',
    description: 'SoccerDescription',
    link: 'http://soccer.' } ]
*/   
Share Improve this question edited Jul 10, 2015 at 16:06 tamiros asked Jul 9, 2015 at 20:51 tamirostamiros 3391 gold badge4 silver badges10 bronze badges
Add a ment  | 

3 Answers 3

Reset to default 3

You're about to learn an awesome new higher-order function, zip! To be honest, I very rarely run into situtations where it is useful, but your example happens to be perfect for it.

/*
 Example in ES6. In order to run, first install node and then go
  npm install -g babel
  npm install underscore
  babel thisfile.js | node
*/

let _ = require('underscore')

let resp = [
  "Football",
  ['Football', 'Soccer'],
  ['FootballDescription', 'SoccerDescription'],
  ['http://football.', 'http://soccer.']
]

// 1. Throw away the first string, e.g. "Football"
resp.shift()

// 2. Use zip to make an array of intersected arrays, i.e
// [
//   ['Football', 'FootballDescription', 'http://football.'],
//   ['Soccer', 'SoccerDescription', 'http://soccer.']
// ]
// and then use map to make each array into a nicely named object
let objects = _.zip(
  resp[0],
  resp[1],
  resp[2]
).map(x => ({
  name: x[0],
  desc: x[1],
  link: x[2]
}))

console.log(objects)
/*
Output:
[ { name: 'Football',
    description: 'FootballDescription',
    link: 'http://football.' },
  { name: 'Soccer',
    description: 'SoccerDescription',
    link: 'http://soccer.' } ]
*/

There's no need to involve another library if you don't want. Map and filter work here but I think they add a lot of length. I'd favor forEach.

Keep in mind that Array.prototype.forEach passes along up to three parameters to your callback function. In this case you can get by with two.

data[2].forEach(function(elem, index) {
  elem && arr.push({title: data[1][index], desc: elem, link: data[3][index]});
}); 

And a solution using map and filter might look like

data[1].map(function(elem, index) {
  return ({
    title: data[1][index],
    description: data[2][index],
    link: data[3][index]
  });
}).filter(function(elem) {
  return elem.description;
});

Looks like you need some lodash/underscore in your life…

http://underscorejs/ https://lodash./

They are libraries that do exactly that. Take Objects/Arrays and slice and dice them until they are what you want. Super useful.

Or you could just do it in plain ol' reduce…

var crazyArray = ['title here', ['one', 'two', 'three'], ['four', 'five'], '', ['six']]
var reduced = crazyArray.reduce(function( last, cur ){
  if(cur) return last.concat(cur);
  return last;
}, []);
console.log(reduced) // [ 'title here', 'one', 'two', 'three', 'four', 'five', 'six' ]

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

相关推荐

发表回复

评论列表(0条)

  • 暂无评论

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

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

关注微信