Home > Mobile >  Javascript: Compare and Restructure Array Own Values
Javascript: Compare and Restructure Array Own Values

Time:12-28

I have an array with keys: timestamp and price. The timestamps are hourly and I am also using date-fns library to compare if timestamps belong to the same day - if they do, I am trying to sum all price points of that day. However, I am finding some discrepancies as I do so:

Array is spaced out into 3 separate days for clarity purposes:

{
  "prices": [
    [1671818476949, 16854.460790677775],
    [1671822082820, 16845.20394128685],
    [1671825684227, 16857.05646176291],
    [1671829225308, 16829.569665685623],
    [1671832882885, 16825.560754591264],
    [1671836452315, 16802.19013067553],
    [1671840055897, 16791.45543916491],
    [1671843601067, 16828.5039057286],
    [1671847235412, 16818.886333963925],
    [1671850908752, 16828.80915767001],
    [1671854492281, 16849.1353436805],
    [1671858107673, 16844.63646922823],
    [1671861614876, 16826.94422938057],

    [1671865308427, 16830.32100715682],
    [1671868880378, 16859.602706687205],
    [1671872427084, 16838.84722581856],
    [1671876070308, 16843.698114347266],
    [1671879705628, 16833.179777617614],
    [1671883320221, 16826.127986844378],
    [1671886841429, 16835.60904589224],
    [1671890403652, 16826.52735073518],
    [1671894003774, 16840.053047104313],
    [1671897642888, 16844.75966886341],
    [1671901289954, 16846.46639955969],
    [1671904904119, 16846.743046196585],
    [1671908487819, 16849.228682191264],
    [1671912082408, 16853.84096165539],
    [1671915617341, 16848.57056951711],
    [1671919248222, 16838.55847898353],
    [1671922845055, 16847.802247651052],
    [1671926406952, 16848.649159225337],
    [1671930105411, 16849.932721831166],
    [1671933659969, 16848.512350420737],
    [1671937267311, 16836.58057734161],
    [1671940900097, 16842.511784308153],
    [1671944512405, 16837.250031512558],
    [1671948089796, 16835.01977126436],

    [1671951658960, 16837.930437518276],
    [1671955200553, 16831.66911474702],
    [1671958801135, 16841.3948238686],
    [1671962500002, 16839.084643107144],
    [1671966068189, 16834.494972743123],
    [1671969625433, 16833.460321328374],
    [1671973226717, 16832.79193114006],
    [1671976864726, 16814.494641690155],
    [1671980509077, 16781.822451943077],
    [1671984031113, 16821.199913544602],
    [1671987680236, 16820.32217610258],
    [1671991240419, 16807.414662482362],
    [1671994911250, 16794.108452870256],
    [1671998512051, 16769.85904421313],
    [1672002110939, 16772.940684988003],
    [1672005625248, 16820.196694166687],
    [1672009311744, 16813.158456662797],
    [1672012841914, 16842.72026144195],
    [1672016506486, 16843.359409890574],
    [1672020041689, 16852.772718398166],
    [1672023659844, 16883.023913256362],
    [1672027284022, 16895.732317171107],
    [1672030862669, 16882.371697632705],

    [1672034480606, 16862.501900560783],
    [1672038111850, 16853.824750006406],
    [1672041654416, 16845.9569876033],
    [1672045227499, 16843.843448135598],
    [1672048916306, 16848.912074255015],
    [1672052466904, 16859.749930767142],
    [1672056072318, 16865.679924348886],
    [1672059600720, 16862.520948313442],
    [1672063223636, 16840.16651774838],
    [1672066882254, 16836.402019038687],
    [1672070414455, 16818.749629565693],
    [1672074026355, 16841.011497434578],
    [1672077687367, 16841.16468121544],
    [1672081285285, 16823.19653988069],
    [1672084914724, 16846.539413040075],
    [1672088451149, 16844.521298565145],
    [1672092105680, 16839.48881574047],
    [1672095707553, 16843.692990272582],
    [1672099308191, 16895.753539841488],
    [1672102868807, 16869.94367902591],
    [1672106436652, 16869.681983132617],
    [1672110025423, 16889.298174537],
    [1672113676425, 16869.264589868446],
    [1672117308026, 16890.08282608721],
    [1672120880596, 16875.43904573174],

    [1672124490175, 16876.94990058372],
    [1672128063768, 16869.15484593176],
    [1672131709243, 16861.249964108203],
    [1672135267379, 16886.480841768516],
    [1672138903770, 16865.316599966118],
    [1672142409979, 16835.8325998708],
    [1672146052583, 16808.706816185026],
    [1672149645559, 16825.2039722797],
    [1672153287438, 16777.896913134075],
    [1672156909469, 16795.71982274382],
    [1672160506962, 16778.505439723354]
  ]
}

I have tried the following:

let sumPrice = 0;
let priceArr = [];
for (let i = 0; i < coinHistory.prices?.length; i  ) {
  const coin = coinHistory.prices[i];
  const currentDate = coin[0];
  const currentPrice = coin[1];
  if (i === 0) {
    sumPrice = currentPrice;
  }

  if (i >= 1) {
    const prevDate = coinHistory.prices[i - 1][0];
    const prevPrice = coinHistory.prices[i - 1][1];
    const stillSameDay = isSameDay(currentDate,prevDate);

      if (stillSameDay) {
         sumPrice  = currentPrice;
      } else{
        priceArr.push({timeStampDate: prevDate 
        ,totalDailySum: sumPrice});
        sumPrice = currentPrice;
      }
  }
}

The result I get:

[
{timeStampDate: 1671861614876, totalDailySum: 218802.4126234967},
{timeStampDate: 1671948089796, totalDailySum: 404208.3927127256}, 
{timeStampDate: 1672034480606, totalDailySum: 403928.82564146793}, 
{timeStampDate: 1672120880596, totalDailySum: 404514.88530415593}
]

As you can see, results does not include the timeStamp from 1672124490175 onwards, which is the 27th of the month and is different than 1672120880596 which is the 26th of the month.

Expected input:

[
{timeStampDate: 1671861614876, totalDailySum: TOTAL_PRICES_FOR_ALL_MATHING_TIMESTAMPS},
{timeStampDate: 1671948089796, totalDailySum: TOTAL_PRICES_FOR_ALL_MATHING_TIMESTAMPS}, 
{timeStampDate: 1672034480606, totalDailySum: TOTAL_PRICES_FOR_ALL_MATHING_TIMESTAMPS}, 
{timeStampDate: 1672120880596, totalDailySum: TOTAL_PRICES_FOR_ALL_MATHING_TIMESTAMPS},
{timeStampDate: 1672160506962, totalDailySum: TOTAL_PRICES_FOR_ALL_MATHING_TIMESTAMPS}
]

CodePudding user response:

Your code is fine. You just forgot a little detail: you only store a value in the result array, if you encounter a new date. After the last day though, no new date can be encountered and the data of the last day is never stored in the array.

To fix that you could for example simply add a special case where you push the data of the last day onto the array:

if (i   1 === coinHistory.prices.length) {
  priceArr.push({
    timeStampDate: currentDate,
    totalDailySum: sumPrice
  });
}

Here is the complete working code I used to test it:

function isSameDay(d1, d2) {
  d1 = new Date(d1)
  d2 = new Date(d2)
  return d1.getFullYear() === d2.getFullYear() &&
    d1.getMonth() === d2.getMonth() &&
    d1.getDate() === d2.getDate();
}


let sumPrice = 0;
let priceArr = [];
for (let i = 0; i < coinHistory.prices.length; i  ) {
  const coin = coinHistory.prices[i];
  const currentDate = coin[0];
  const currentPrice = coin[1];
  if (i !== 0) {
    const prevDate = coinHistory.prices[i - 1][0];
    const prevPrice = coinHistory.prices[i - 1][1];

    if (!isSameDay(currentDate, prevDate)) {
      priceArr.push({
        timeStampDate: prevDate,
        totalDailySum: sumPrice
      });
      sumPrice = 0; // reset
    }
  }
  sumPrice  = currentPrice;

    // save the last day
  if (i   1 === coinHistory.prices.length) {
    priceArr.push({
      timeStampDate: currentDate,
      totalDailySum: sumPrice
    });
  }
}


console.log(priceArr)
<script>
  window.coinHistory = {
    prices: [
      [1671818476949, 16854.460790677775],
      [1671822082820, 16845.20394128685],
      [1671825684227, 16857.05646176291],
      [1671829225308, 16829.569665685623],
      [1671832882885, 16825.560754591264],
      [1671836452315, 16802.19013067553],
      [1671840055897, 16791.45543916491],
      [1671843601067, 16828.5039057286],
      [1671847235412, 16818.886333963925],
      [1671850908752, 16828.80915767001],
      [1671854492281, 16849.1353436805],
      [1671858107673, 16844.63646922823],
      [1671861614876, 16826.94422938057],

      [1671865308427, 16830.32100715682],
      [1671868880378, 16859.602706687205],
      [1671872427084, 16838.84722581856],
      [1671876070308, 16843.698114347266],
      [1671879705628, 16833.179777617614],
      [1671883320221, 16826.127986844378],
      [1671886841429, 16835.60904589224],
      [1671890403652, 16826.52735073518],
      [1671894003774, 16840.053047104313],
      [1671897642888, 16844.75966886341],
      [1671901289954, 16846.46639955969],
      [1671904904119, 16846.743046196585],
      [1671908487819, 16849.228682191264],
      [1671912082408, 16853.84096165539],
      [1671915617341, 16848.57056951711],
      [1671919248222, 16838.55847898353],
      [1671922845055, 16847.802247651052],
      [1671926406952, 16848.649159225337],
      [1671930105411, 16849.932721831166],
      [1671933659969, 16848.512350420737],
      [1671937267311, 16836.58057734161],
      [1671940900097, 16842.511784308153],
      [1671944512405, 16837.250031512558],
      [1671948089796, 16835.01977126436],

      [1671951658960, 16837.930437518276],
      [1671955200553, 16831.66911474702],
      [1671958801135, 16841.3948238686],
      [1671962500002, 16839.084643107144],
      [1671966068189, 16834.494972743123],
      [1671969625433, 16833.460321328374],
      [1671973226717, 16832.79193114006],
      [1671976864726, 16814.494641690155],
      [1671980509077, 16781.822451943077],
      [1671984031113, 16821.199913544602],
      [1671987680236, 16820.32217610258],
      [1671991240419, 16807.414662482362],
      [1671994911250, 16794.108452870256],
      [1671998512051, 16769.85904421313],
      [1672002110939, 16772.940684988003],
      [1672005625248, 16820.196694166687],
      [1672009311744, 16813.158456662797],
      [1672012841914, 16842.72026144195],
      [1672016506486, 16843.359409890574],
      [1672020041689, 16852.772718398166],
      [1672023659844, 16883.023913256362],
      [1672027284022, 16895.732317171107],
      [1672030862669, 16882.371697632705],

      [1672034480606, 16862.501900560783],
      [1672038111850, 16853.824750006406],
      [1672041654416, 16845.9569876033],
      [1672045227499, 16843.843448135598],
      [1672048916306, 16848.912074255015],
      [1672052466904, 16859.749930767142],
      [1672056072318, 16865.679924348886],
      [1672059600720, 16862.520948313442],
      [1672063223636, 16840.16651774838],
      [1672066882254, 16836.402019038687],
      [1672070414455, 16818.749629565693],
      [1672074026355, 16841.011497434578],
      [1672077687367, 16841.16468121544],
      [1672081285285, 16823.19653988069],
      [1672084914724, 16846.539413040075],
      [1672088451149, 16844.521298565145],
      [1672092105680, 16839.48881574047],
      [1672095707553, 16843.692990272582],
      [1672099308191, 16895.753539841488],
      [1672102868807, 16869.94367902591],
      [1672106436652, 16869.681983132617],
      [1672110025423, 16889.298174537],
      [1672113676425, 16869.264589868446],
      [1672117308026, 16890.08282608721],
      [1672120880596, 16875.43904573174],

      [1672124490175, 16876.94990058372],
      [1672128063768, 16869.15484593176],
      [1672131709243, 16861.249964108203],
      [1672135267379, 16886.480841768516],
      [1672138903770, 16865.316599966118],
      [1672142409979, 16835.8325998708],
      [1672146052583, 16808.706816185026],
      [1672149645559, 16825.2039722797],
      [1672153287438, 16777.896913134075],
      [1672156909469, 16795.71982274382],
      [1672160506962, 16778.505439723354]
    ]
  }

</script>

https://jsfiddle.net/timlg07/0Ldnt6ko/

CodePudding user response:

This is a multiple step problem.

  1. Group the array of tuple values by date (See Array.prototype.group() - JavaScript | MDN)

    This is actually more involved than it might seem. A calendar "date" is a period between midnight (inclusive) and midnight (exclusive) according to a given time zone. You didn't specify if you want to use Universal Coordinated Time or some arbitrary time zone (e.g. the time zone of the local device), but that decision will potentially alter the results in a substantial way.

  2. After grouping the tuples by date, each date's array must be iterated to total the sum, and then the result pushed into a new array like the one you described for the desired output

Below is a code snippet demonstrating how to perform the above steps using some functional patterns. The date-related functions accept a boolean argument that will allow you to use the local time zone.

function group (array, selector) {
  const result = {};
  for (const element of array) {
    const key = selector(element);
    (result[key] ??= []).push(element);
  }
  return result;
}

function pad (num) {
  return String(num).padStart(2, '0');
}

function getDateKey (timestamp, useLocalTimeZone) {
  const date = new Date(timestamp);
  const year = useLocalTimeZone ? date.getFullYear() : date.getUTCFullYear();
  const month = (useLocalTimeZone ? date.getMonth() : date.getUTCMonth())   1;
  const dayOfMonth = useLocalTimeZone ? date.getDate() : date.getUTCDate();
  return `${year}-${pad(month)}-${pad(dayOfMonth)}`;
}

function groupAndSum (coinHistory, useLocalTimeZone) {
  const groupedByDate = group(
    coinHistory.prices,
    ([timestamp]) => getDateKey(timestamp, useLocalTimeZone),
  );

  const result = [];

  for (const [calendarDate, tuples] of Object.entries(groupedByDate)) {
    let totalDailySum = 0;
    for (const [,price] of tuples) totalDailySum  = price;
    result.push({calendarDate, totalDailySum});
  }

  return result;
}

const coinHistory = {"prices":[[1671818476949,16854.460790677775],[1671822082820,16845.20394128685],[1671825684227,16857.05646176291],[1671829225308,16829.569665685623],[1671832882885,16825.560754591264],[1671836452315,16802.19013067553],[1671840055897,16791.45543916491],[1671843601067,16828.5039057286],[1671847235412,16818.886333963925],[1671850908752,16828.80915767001],[1671854492281,16849.1353436805],[1671858107673,16844.63646922823],[1671861614876,16826.94422938057],[1671865308427,16830.32100715682],[1671868880378,16859.602706687205],[1671872427084,16838.84722581856],[1671876070308,16843.698114347266],[1671879705628,16833.179777617614],[1671883320221,16826.127986844378],[1671886841429,16835.60904589224],[1671890403652,16826.52735073518],[1671894003774,16840.053047104313],[1671897642888,16844.75966886341],[1671901289954,16846.46639955969],[1671904904119,16846.743046196585],[1671908487819,16849.228682191264],[1671912082408,16853.84096165539],[1671915617341,16848.57056951711],[1671919248222,16838.55847898353],[1671922845055,16847.802247651052],[1671926406952,16848.649159225337],[1671930105411,16849.932721831166],[1671933659969,16848.512350420737],[1671937267311,16836.58057734161],[1671940900097,16842.511784308153],[1671944512405,16837.250031512558],[1671948089796,16835.01977126436],[1671951658960,16837.930437518276],[1671955200553,16831.66911474702],[1671958801135,16841.3948238686],[1671962500002,16839.084643107144],[1671966068189,16834.494972743123],[1671969625433,16833.460321328374],[1671973226717,16832.79193114006],[1671976864726,16814.494641690155],[1671980509077,16781.822451943077],[1671984031113,16821.199913544602],[1671987680236,16820.32217610258],[1671991240419,16807.414662482362],[1671994911250,16794.108452870256],[1671998512051,16769.85904421313],[1672002110939,16772.940684988003],[1672005625248,16820.196694166687],[1672009311744,16813.158456662797],[1672012841914,16842.72026144195],[1672016506486,16843.359409890574],[1672020041689,16852.772718398166],[1672023659844,16883.023913256362],[1672027284022,16895.732317171107],[1672030862669,16882.371697632705],[1672034480606,16862.501900560783],[1672038111850,16853.824750006406],[1672041654416,16845.9569876033],[1672045227499,16843.843448135598],[1672048916306,16848.912074255015],[1672052466904,16859.749930767142],[1672056072318,16865.679924348886],[1672059600720,16862.520948313442],[1672063223636,16840.16651774838],[1672066882254,16836.402019038687],[1672070414455,16818.749629565693],[1672074026355,16841.011497434578],[1672077687367,16841.16468121544],[1672081285285,16823.19653988069],[1672084914724,16846.539413040075],[1672088451149,16844.521298565145],[1672092105680,16839.48881574047],[1672095707553,16843.692990272582],[1672099308191,16895.753539841488],[1672102868807,16869.94367902591],[1672106436652,16869.681983132617],[1672110025423,16889.298174537],[1672113676425,16869.264589868446],[1672117308026,16890.08282608721],[1672120880596,16875.43904573174],[1672124490175,16876.94990058372],[1672128063768,16869.15484593176],[1672131709243,16861.249964108203],[1672135267379,16886.480841768516],[1672138903770,16865.316599966118],[1672142409979,16835.8325998708],[1672146052583,16808.706816185026],[1672149645559,16825.2039722797],[1672153287438,16777.896913134075],[1672156909469,16795.71982274382],[1672160506962,16778.505439723354]]};

const outputUtc = groupAndSum(coinHistory);
console.log('UTC:', outputUtc);

const outputLocal = groupAndSum(coinHistory, true);
console.log('Local:', outputLocal);

  • Related