规范化嵌套字典中所有键的值并附加为新的 key/value 对

Normalize values for all keys in nested dictionaries and append as new key/value pairs

假设我有一个带有嵌套子词典的字典:

let dict = 
{
    "SEATTLE" :     {
        "gross_sales" : 106766,
        "price" : 584.50,
        "dates" : [             {
                "date" : "2020-03-13",
                "total_sales_to_date" : 2,
                "new_sales" : 2,
            }
,           {
                "date" : "2020-03-19",
                "total_sales_to_date" : 5,
                "new_sales" : 3,
            }
 ]
    }
,   
    "PHOENIX" :     {
        "gross_sales" : 26691.5,
        "price" : 292.25,
        "dates" : [             {
                "date" : "2020-03-13",
                "total_sales_to_date" : 9,
                "new_sales" : 9,
            }
,           {
                "date" : "2020-03-19",
                "total_sales_to_date" : 19,
                "new_sales" : 10,
            }
 ]
    }

}

我想将 key/value 对中的每个数值相对于其他 key/value 标准化,然后将它们附加为 new key/value对。

对于时间序列数据的 dates 数组,我想将每个日期中的每个 key/value 对针对时间(数组内)和同一时间的其他位置进行归一化日期(其他对象)。

比如我术后求的是这样的:

{
    "SEATTLE" :     {
        "gross_sales" : 106766,
        "normalised_gross_sales" : 1.0,
        "price" : 584.50,
        "normalised_price" : 1.0, 
        "dates" : [             {
                "date" : "2020-03-13",
                "total_sales_to_date" : 2,
                "norm_total_sales_over_time" : 0.4, 
                "norm_total_sales_over_locations" : 0.22222222, 
                "new_sales" : 2,
            }
,           {
                "date" : "2020-03-19",
                "total_sales_to_date" : 5,
                "norm_total_sales_over_time" : 1.0, 
                "norm_total_sales_over_locations" : 0.26315789, 
                "new_sales" : 3,
            }
 ]
    }
,   
    "PHOENIX" :     {
        "gross_sales" : 26691.5,
        "normalised_gross_sales" : 0.25,
        "price" : 292.25,
        "normalised_price" : 0.5,  
        "dates" : [             {
                "date" : "2020-03-13",
                "total_sales_to_date" : 9,
                "norm_total_sales_over_time" : 0.47368421, 
                "norm_total_sales_over_locations" : 1.0, 
                "new_sales" : 9,
            }
,           {
                "date" : "2020-03-19",
                "total_sales_to_date" : 19,
                "norm_total_sales_over_time" : 1.0, 
                "norm_total_sales_over_locations" : 1.0, 
                "new_sales" : 10,
            }
 ]
    }

}

即:数组中最后一个日期的 total_sales_to_date 值应归一化为 1.0norm_total_sales_over_time

和数组中当前日期的所有对象(SEATTLEPHOENIX)的最大 total_sales_to_date 值应归一化为 1.0,如 norm_total_sales_over_locations

我发现这在 JS 中处理起来非常复杂。我的实际任务涉及包含数百个我需要比较的子词典的词典,我正在寻找可扩展的解决方案。在 pandas dataframe 中,这将是微不足道的,但是我想学习如何使用现代 javascript 来解决这个问题,因为我 运行 这个过程来自 node.js 使用 ES6 解释器。

什么是有效的 ES6 javascript 解决方案?

这是一个解决方案,returns 以描述的方式标准化值:

let dict = {
  "SEATTLE": {
    "gross_sales": 106766,
    "price": 584.50,
    "dates": [{
      "date": "2020-03-13",
      "total_sales_to_date": 2,
      "new_sales": 2,
    }, {
      "date": "2020-03-19",
      "total_sales_to_date": 5,
      "new_sales": 3,
    }]
  },
  "PHOENIX": {
    "gross_sales": 26691.5,
    "price": 292.25,
    "dates": [{
      "date": "2020-03-13",
      "total_sales_to_date": 9,
      "new_sales": 9,
    }, {
      "date": "2020-03-19",
      "total_sales_to_date": 19,
      "new_sales": 10,
    }]
  }

}


async function normaliseDict(_dict) {

  let values = await Object.values(_dict);
  // make arrays with values from each key
  let all_gross_sales = [];
  let all_price = [];
  let all_total_sales = {};

  values.forEach((element) => {
    all_gross_sales.push(element.gross_sales);
    all_price.push(element.price);

    let most_recent_total_sales_value = element.dates[element.dates.length - 1].total_sales_to_date;

    element.dates.forEach((date, idx) => {
      date.norm_total_sales_over_time = date.total_sales_to_date / most_recent_total_sales_value;
      if (all_total_sales[date.date]) all_total_sales[date.date].push(date.total_sales_to_date);
      else {
        all_total_sales[date.date] = [];
        all_total_sales[date.date].push(date.total_sales_to_date);
      }
    });

  });

  const newDict = values.map(ob => {
    ob.gross_sales_norm = ob.gross_sales / Math.max(...all_gross_sales);
    ob.price_norm = ob.price / Math.max(...all_price);
    return ob;
  });

  values.forEach((element) => {
    element.dates.forEach((date, idx) => {
      date.norm_total_sales_over_locations_for_this_date = date.total_sales_to_date / Math.max(...all_total_sales[date.date]);
    });
  });
  return await dict;
}


(async () => {
  console.log(await normaliseDict(dict))
})()