2015-11-16 1 views
0

partir d'un tableau d'objets représentant les actions, leurs prix au comptant et d'autres propriétés telles queréduction JS idiomatiques et fonctionnelle du tableau d'objets avec prédicat

stocks = [ { ticker: 'GOOG', price: 206, ... }, 
      { ticker: 'AAPL', price: 47, ... }, 
      { ticker: 'MSFT', price: 39, ... }, 
      { ticker: 'GOOG', price: 159, ... }, 
      { ticker: 'MSFT', price: 39, ... }, 
      { ticker: 'MSFT', price: 21, ... }, 
      { ticker: 'GOOG', price: 80, ... }, 
      { ticker: 'AAPL', price: 20, ... }, 
      { ticker: 'AAPL', price: 73, ... }, 
      { ticker: 'MSFT', price: 49, ... }, 
      ... ]; 

Je voudrais revenir un tableau réduit avec, pour chaque ticker, l'objet ayant le prix maximum (et les autres propriétés) d'une manière fonctionnelle.

Voici ce que j'ai jusqu'à présent:

c.reduce(function(acc, y) { 
    return acc 
    .filter(function(x) { return x.ticker!=y.ticker }) 
    .concat(
     acc.filter(function(x) { return x.ticker==y.ticker }) 
     .concat([y]) 
     .reduce(function(u,v) { 
      return u.price > v.price ? u : v }) /* predicate */ 
    ) 
}, []); 

Mais est-il un moyen JavaScript plus idiomatiques de le faire? Underscore et lodash sont les bienvenus mais s'il vous plaît pas jQuery.

Répondre

0

Avec lodash:

var res = _(stocks) 
    // group all elements by 'ticker' 
    .groupBy(function (s) { 
     return s.ticker; 
    // sort each group by price descending and get the first element (the max) 
    }).map(function (n) { 
     return _(n).sortBy(n, function (v) { 
      return -v.price; 
     }).first(); 
    }); 

console.log(JSON.stringify(res, null, 4)); 

Ce code donne:

[ 
    { 
     "ticker": "GOOG", 
     "price": 206 
    }, 
    { 
     "ticker": "AAPL", 
     "price": 73 
    }, 
    { 
     "ticker": "MSFT", 
     "price": 49 
    } 
] 

version écourtée de tri ASC et obtenir le dernier élément:

var res = _(stocks) 
    .groupBy('ticker') 
    .map(function (n) { 
     return _(n).sortBy('price').last(); 
    }); 
+0

Mes excuses. Veuillez réessayer mon code, j'ai fait référence à 'x.stock' d'une version précédente au lieu de' x.ticker'. Merci pour votre message! –

+0

Note: J'utiliserais '_.first()' au lieu de '(...) [0]'. –

+0

Mieux avec 'first()', j'ai édité mon post. – Shanoor

0

J'ai essayé de résoudre cette tâche avec fonctionnelle concept.

var stocks = 
    [ 
    {ticker: 'GOOG', price: 206}, 
    {ticker: 'AAPL', price: 47}, 
    {ticker: 'MSFT', price: 39}, 
    {ticker: 'GOOG', price: 159}, 
    {ticker: 'MSFT', price: 39}, 
    {ticker: 'MSFT', price: 21}, 
    {ticker: 'GOOG', price: 80}, 
    {ticker: 'AAPL', price: 20}, 
    {ticker: 'AAPL', price: 73}, 
    {ticker: 'MSFT', price: 49} 
]; 

var result = stocks.reduce(function (acc, next) { 
    return acc 
     .filter(function (stock) { 
      return stock.ticker != next.ticker 
     }) 
     .concat(acc.reduce(function (u, v) { 
      return u.ticker == v.ticker && u.price < v.price ? v : u; 
     }, next)); 
}, []); 


console.log(result); 

Sortie

[ 
{ ticker: 'GOOG', price: 206 }, 
{ ticker: 'AAPL', price: 73 }, 
{ ticker: 'MSFT', price: 49 } 
] 
+0

à quel point cela diffère-t-il de ma propre solution? –

+0

Il y avait une erreur. Non? Quand j'ai copié ton code, ça m'a donné une mauvaise réponse. –

0

Voici une solution pure JavaScript sans cadre qui utilise un seul filter() et un reduce():

code

var stocks = [ { ticker: 'GOOG', price: 206}, 
      { ticker: 'AAPL', price: 47}, 
      { ticker: 'MSFT', price: 39}, 
      { ticker: 'GOOG', price: 159}, 
      { ticker: 'MSFT', price: 39}, 
      { ticker: 'MSFT', price: 21}, 
      { ticker: 'GOOG', price: 80}, 
      { ticker: 'AAPL', price: 20}, 
      { ticker: 'AAPL', price: 73}, 
      { ticker: 'MSFT', price: 49}]; 

function max(arr) { 
    return arr.filter(function(item){ 
    return this[item.ticker] === item; 
    }.bind(arr.reduce(function(res, cur) { 
    return (res[cur.ticker] = (res[cur.ticker] 
     ? (res[cur.ticker].price > cur.price ? res[cur.ticker] : cur) 
     : cur 
    )), res; 
    }, {}))); 
} 

console.log(max(stocks)); 

Résultat

[ 
{ ticker: 'GOOG', price: 206 }, 
{ ticker: 'AAPL', price: 73 }, 
{ ticker: 'MSFT', price: 49 } 
] 

JSBin

https://jsbin.com/linevudika/edit?js,console