Tengo una variedad de objetos, baseAsset key y Volume son parte de cada objeto pero el volumen es diferente para cada objeto.

Quiero hacer coincidir la clave baseAsset y devolver el objeto con el valor de volumen más alto. La eficiencia y la velocidad son importantes ya que la matriz tiene más de 3000 objetos

let tickerA = [{
    pair: 'AUDUSD',
    baseAsset: 'AUD',
    lastPriceUSD: 0.74,
    volume: 1000
}, {
    pair: 'AUDUSD',
    baseAsset: 'AUD',
    lastPriceUSD: 0.76,
    volume: 2000
}, {
    pair: 'USDEUR',
    baseAsset: 'USD',
    lastPriceUSD: 1.25,
    volume: 1200
}, {
    pair: 'USDEUR',
    baseAsset: 'USD',
    lastPriceUSD: 1.19,
    volume: 1500
}]

Retorno esperado de una función

tickerB = [{
    baseAsset: 'AUD',
    lastPriceUSD: 0.76,
    volume: 2000
}, {
    baseAsset: 'USD',
    lastPriceUSD: 1.25,
    volume: 1500
}]
4
Tayyab Rahman 11 may. 2019 a las 02:06

4 respuestas

La mejor respuesta

Puede hacerlo en tiempo O (n) haciendo un bucle y guardando el elemento más grande en un objeto. Al final, sus valores estarán en Object.values de los grupos:

let tickerA = [{pair: 'AUDUSD',baseAsset: 'AUD',lastPriceUSD: 0.74,volume: 1000}, {pair: 'AUDUSD',baseAsset: 'AUD',lastPriceUSD: 0.76,volume: 2000}, {pair: 'USDEUR',baseAsset: 'USD',lastPriceUSD: 1.25,volume: 1200}, {pair: 'USDEUR',baseAsset: 'USD',lastPriceUSD: 1.19,volume: 1500}]

let groups = tickerA.reduce((largest, {baseAsset, lastPriceUSD, volume}) => {
    /* 
     * if it's a new baseAsset or bigger than a previous one, save it
     * to the group under the baseAsset key 
    */
    if (!largest[baseAsset] || largest[baseAsset]['volume'] < volume ) {
        largest[baseAsset] = {baseAsset, lastPriceUSD, volume}
    }

    return largest
}, {})

TickerB = Object.values(groups)
console.log(TickerB)
1
Mark Meyer 10 may. 2019 a las 23:27

Esta alternativa agrupa baseAsset y al final extrae los valores agrupados.

Esta es una O(n) complejidad de tiempo .

let tickerA = [{pair: 'AUDUSD',baseAsset: 'AUD',lastPriceUSD: 0.74,volume: 1000}, {pair: 'AUDUSD',baseAsset: 'AUD',lastPriceUSD: 0.76,volume: 2000}, {pair: 'USDEUR',baseAsset: 'USD',lastPriceUSD: 1.25,volume: 1200}, {pair: 'USDEUR',baseAsset: 'USD',lastPriceUSD: 1.19,volume: 1500}];
let result = Object.values(tickerA.reduce((a, {baseAsset, lastPriceUSD, volume}) => {
    let {volume: current} = a[baseAsset] || {volume: Number.MAX_SAFE_INTEGER};
    
    if (current < volume) a[baseAsset].volume = volume;
    else a[baseAsset] = {baseAsset, lastPriceUSD, volume};
    
    return a;
}, Object.create(null)));

console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
0
Ele 10 may. 2019 a las 23:20

Un enfoque sería iterar los valores de tickerA y asignarlos a las teclas baseAsset si el valor volume de ese elemento es mayor que el del elemento actual de esa clave baseAsset:

let tickerA = [{
    pair: 'AUDUSD',
    baseAsset: 'AUD',
    lastPriceUSD: 0.74,
    volume: 1000
}, {
    pair: 'AUDUSD',
    baseAsset: 'AUD',
    lastPriceUSD: 0.76,
    volume: 2000
}, {
    pair: 'USDEUR',
    baseAsset: 'USD',
    lastPriceUSD: 1.25,
    volume: 1200
}, {
    pair: 'USDEUR',
    baseAsset: 'USD',
    lastPriceUSD: 1.19,
    volume: 1500
}];

/* Use map to relate baseAsset key of tickerA item with current max volume value */
const map = new Map()

/* Iterate tickerA items, searching for greatest volume value per baseAsset class */
for(const item of tickerA) {
  
  const assetMatch = map.get(item.baseAsset);
  
  if(assetMatch && item.volume < assetMatch.volume) {
    /* If matching item (by asset found) with volume greater than that of current tickerA
    item, then disregard the current item */
    continue;
  }
  else {
    /* Otherwise, this tickerA item is; the first of the asset class, or greater in volume
    so we'll update the map entry for this asset class */
    map.set(item.baseAsset, item);
  }  
}
 
/* Extract the map values as an array */
const tickerB = Array.from(map.values());

console.log(tickerB);
1
Dacre Denny 10 may. 2019 a las 23:25

Utilice reduce y Object.values:

let tickerA = [{pair: 'AUDUSD',baseAsset: 'AUD',lastPriceUSD: 0.74,volume: 1000}, {pair: 'AUDUSD',baseAsset: 'AUD',lastPriceUSD: 0.76,volume: 2000}, {pair: 'USDEUR',baseAsset: 'USD',lastPriceUSD: 1.25,volume: 1200}, {pair: 'USDEUR',baseAsset: 'USD',lastPriceUSD: 1.19,volume: 1500}];
const res = Object.values(tickerA.reduce((acc, { baseAsset, lastPriceUSD, volume }) => {
  acc[baseAsset] = (!acc[baseAsset] || acc[baseAsset].volume < volume) ? { baseAsset, lastPriceUSD, volume } : acc[baseAsset];
  return acc;
}, {}));
console.log(res);
.as-console-wrapper { max-height: 100% !important; top: auto; }
0
Jack Bashford 10 may. 2019 a las 23:20