2016-07-22 15 views
12

Ich habe [3, 16, 120]. Wenn ich [3, 16, 120].map(mapper) mache, möchte ich zum Beispiel [4,5, 17,18, 121,122] erreichen, d.h. jedes Element wird auf n + 1 und n + 2 abgebildet. Dies ist natürlich ein Beispiel - was ich will ist, einfach mehrere Werte aus Mapper - FunktionArray.map 1 Element zu Mehrfachelement

Push Ich muss Array.each verwenden und Push an ein Array, oder ist es möglich, es mit Array.map (oder tun andere integrierte API)

+0

Sie könnten wahrscheinlich 'Array.reduce' verwenden, obwohl ich nicht sicher bin, würde es besser sein, als' Array.forEach' verwenden. – jcaron

Antwort

8

Nicht besonders schön, aber es ist eine mögliche Lösung:

var arr = [3, 16, 120]; 
 

 
console.log([].concat.apply([], arr.map(function (n) { return [n+1, n+2]; })));

+0

sollten Sie' Array.prototype.concat' betrachten anstelle von '[] .concat'. Es ist zwar kürzer, aber Sie vergeben jedes Mal ein neues Array. – eltonkamami

+1

@eltonkamami Ich bin sowieso schon n + 3 Arrays zugewiesen. n + 4 wird die Dinge nicht viel schlimmer machen. – melpomene

13

Sie können reduce() verwenden und zum Array e+1, e+2 jedes Elements hinzufügen.

var ar = [3, 16, 120]; 
 

 
var result = ar.reduce(function(r, e) { 
 
    r.push(e+1, e+2); 
 
    return r; 
 
}, []); 
 

 
console.log(result)

Dies ist ES6 Version mit Pfeil Funktion

var ar = [3, 16, 120]; 
 

 
var result = ar.reduce((r, e) => r.push(e+1, e+2) && r, []); 
 
console.log(result)

PS: Array.push schneller zu sein scheint, und hat keine Maximum call stack.. Fehler, siehe weiter unten :

a = Array(1000000).fill(1); st = Date.now(); Array.prototype.concat.apply([], a.map(function (n) { return [n+1, n+2]; })); console.log(`${Date.now() - st}ms `); 
> RangeError: Maximum call stack size exceeded 

a = Array(1000000).fill(1); st = Date.now(); a.reduce((r, e) => r.push(e+1, e+2) && r, []); console.log(`${Date.now() - st}ms `); 
> 180ms 

So ist der Push im Vergleich zur akzeptierten Lösung vorzuziehen.

+0

Sie modifizieren 'r' im Callback, was bedeutet, dass dies nur eine unnötig komplizierte For-Schleife ist. – melpomene

+0

Ich habe gerade einen Leistungstest hinzugefügt, um zu antworten, und es scheint zu sein, dass ".push" in diesem Fall dem Vergleich mit ".concat" vorzuziehen ist. Concat wird auch 'Maximale Aufrufstack'-Ausnahme für große Arrays werfen – Kostanos

4

Sie ein Array für jedes Einzelteile produzieren könnte, dann concat all diesen Arrays:

[3, 16, 120].map(x => [x+1, x+2]).reduce((acc,val) => acc.concat(val), []); 
+0

Schön, aber es passiert 2 Durchgänge des Arrays und verdoppelte Array – Boyang

+0

Ja, ich denke @Nenad Vracar Lösung ist besser als meine –

1

unter Verwendung von Array#concat und Array#map

Array.prototype.concat.apply([], [3, 16, 120].map(x => [x+1, x+2])); 
2

Just for fun, eine ES6 Lösung mit einem Generator:

var arr = [3, 16, 120]; 
 

 
var [...result] = (function*() { for(i of arr){ yield ++i; yield ++i; }})(); 
 

 
console.log(result);

+0

Ich weiß nie, das kann funktionieren ... 1. Generator kann mit Spread-Operator erweitert werden (gut, es ist iterierbar) 2. Spread-Operator ist langsamer als die Zuweisung Gute Eins! – Boyang

4

Sie Array#reduce in Kombination mit Array#concat nutzen könnten.

console.log([3, 16, 120].reduce(function (r, a) { 
 
    return r.concat(a + 1, a + 2); 
 
}, []));

ES6

console.log([3, 16, 120].reduce((r, a) => r.concat(a + 1, a + 2), []));

+0

Das hat perfekt für mein Szenario funktioniert, danke –

14

ich mit einem selbst kommen, Spread-Operator.

[].concat(...[3, 16, 120].map(x => [x+1, x+2]))