2015-07-09 27 views
1

使用地圖和多個陣列過濾器使用維基百科的API我有一個對象,它看起來像這樣:中的對象

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

第一個數組包含標題,二是描述和第三是鏈接

一些描述可以是空的(「」)。

示例 -

Example

我想所有的三個陣列組合成一個陣列如下:

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

只有結合如果說明不是空 - obj[2][i] !== ""

我設法使用循環,如果做到這一點:

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

是否有使用JavaScript的高階功能更優雅的方式達到同樣的方法嗎?如mapfilter(也許reduce?)

感謝

編輯:

我做到了,在結束的方式是:

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

// 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.com'], 
// ['Soccer', 'SoccerDescription', 'http://soccer.com'] 
// ] 
// 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.com' }, 
    { name: 'Soccer', 
    description: 'SoccerDescription', 
    link: 'http://soccer.com' } ] 
*/ 

回答

1

你要學習的真棒新的高階函數,拉鍊!說實話,我很少碰到它有用的情況,但你的例子恰好是它的完美。

/* 
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.com', 'http://soccer.com'] 
] 

// 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.com'], 
// ['Soccer', 'SoccerDescription', 'http://soccer.com'] 
// ] 
// 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.com' }, 
    { name: 'Soccer', 
    description: 'SoccerDescription', 
    link: 'http://soccer.com' } ] 
*/ 
+0

太棒了!我將你的答案與http://stackoverflow.com/a/10284006/3237212的幫助相結合,並且收到我認爲很好看的解決方案:)查看我編輯的問題 – tamiros

1

看起來像你需要一些lodash /強調在你的生活......

http://underscorejs.org/ https://lodash.com/

它們是做到這些庫。採取對象/陣列,切片和切塊,直到他們是你想要的。超級有用。

或者你可以做它在純醇」減少......

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' ] 
+0

我會查看underscore.js。 – tamiros

2

沒有必要涉及到另一個庫,如果你不想要的。地圖和過濾工作在這裏,但我認爲他們增加了很多長度。我贊成forEach。

請記住,Array.prototype.forEach將最多三個參數傳遞給您的回調函數。在這種情況下,你可以通過兩個。

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

而使用地圖和過濾器的解決方案可能看起來像

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; 
}); 
+0

似乎我會堅持forEach。在這種情況下,映射和過濾器會增加額外的複雜性。謝謝。 – tamiros