【问题标题】:How to assign data by name string using reduce如何使用reduce按名称字符串分配数据
【发布时间】:2022-01-22 03:22:54
【问题描述】:

我有数据数组

还有这样的减少:

const productMapData = [{
    "occurredAt": "2021-09-20T00:00:00.000",
    "soldTickets": 3836,
    "soldRevenue": 70762,
    "playedOffTickets": 2068,
    "playedOffRevenue": 41429.5,
    "changeInPeriodTickets": 1768,
    "changeInPeriodRevenue": 29332.5,
    "eopAdvanceTickets": 1768,
    "eopAdvanceRevenue": 29332.5,
    "advanceTickets": 1500,
    "advanceRevenue": 11521
  },
  {
    "occurredAt": "2021-09-27T00:00:00.000",
    "soldTickets": 4708,
    "soldRevenue": 88647.5,
    "playedOffTickets": 2127,
    "playedOffRevenue": 49526.5,
    "changeInPeriodTickets": 2581,
    "changeInPeriodRevenue": 39121,
    "eopAdvanceTickets": 2581,
    "eopAdvanceRevenue": 39121,
    "advanceTickets": 700,
    "advanceRevenue": 9521
  },
  {
    "occurredAt": "2021-10-04T00:00:00.000",
    "soldTickets": 5514,
    "soldRevenue": 93969.5,
    "playedOffTickets": 988,
    "playedOffRevenue": 9983,
    "changeInPeriodTickets": 4526,
    "changeInPeriodRevenue": 83986.5,
    "eopAdvanceTickets": 4526,
    "eopAdvanceRevenue": 83986.5,
    "advanceTickets": 1730,
    "advanceRevenue": 14650
  },
  {
    "occurredAt": "2021-10-11T00:00:00.000",
    "soldTickets": 7598,
    "soldRevenue": 109059.5,
    "playedOffTickets": 1476,
    "playedOffRevenue": 16474.5,
    "changeInPeriodTickets": 6122,
    "changeInPeriodRevenue": 92585,
    "eopAdvanceTickets": 6122,
    "eopAdvanceRevenue": 92585,
    "advanceTickets": 800,
    "advanceRevenue": 7560
  },
];

const mapWaterfallChartData = () => productMapData.reduce((previous, point) => {
  const names = ['sopAdvance', 'playedOff', 'sales', 'eopAdvance'];
  const name = names.map(name => name);
  previous[name] = previous[name] || {
    data: [],
    total: 0
  };
  const sopAdvance = point.advanceTickets;
  const playedOff = point.playedOffTickets;
  const sales = point.soldTickets;
  const eopAdvance = point.eopAdvanceTickets;
  return previous;
}, {});

console.log(mapWaterfallChartData(productMapData))

我想要实现的是创建具有namey 值的新对象,其中名称将是名称数组中的值,y 将是属于该名称的值。像这样的:

[
  {
    name: 'sopAdvance',
    y: 4730
  },
  {
    name: 'playedOff',
    y: 6659
  },
  {
    name: 'sales',
    y: 21656
  },
  {
    name: 'eopAdvance',
    y: 14997
  }
]

我对如何做到这一点感到困惑和困惑,因此我们将不胜感激。

【问题讨论】:

  • 部分问题是您在没有充分理由的情况下陷入了使用reduce 的陷阱,这可能是您遇到的主要问题。我猜你收到错误“无法设置undefined 的属性。那是因为你永远不会从reduce 回调中返回previous,等等下一次通过previousundefined. 相反,只是使用一个简单的循环。(reduce 非常适合使用预定义的、可重用的 reducer 函数进行函数式编程。如果不是,那只是编写循环的一种复杂且容易出错的方法。)
  • const name = names.map(name => name); previous[name] = previous[name] || ... - namenames 的副本,因此它也是一个所有名称的数组o.O
  • 结果应该是什么?我不能从代码中完全分辨出来。
  • @T.J.Crowder 按“名称”(及其各自的属性)分组并将它们的值相加
  • @mplungjan 很好,我从你的第一个答案中得到了它,这就是我需要的。谢谢!

标签: javascript ecmascript-6 reduce


【解决方案1】:

部分问题是您在没有充分理由的情况下陷入了使用reduce 的陷阱,这可能是您遇到的主要问题。我猜您收到错误“无法设置undefined 的属性”。那是因为你永远不会从你的reduce 回调中返回previous,等等下一次传递previousundefined.

当然可以加return

    return previous;
}, {});

但坦率地说,只使用循环更简单明了。

不过还有一些其他问题。

  • const name = names.map(name => name); 只是复制 names 数组。
  • 没有任何东西将值一起收集到一个对象中。
  • 总数没有增加。

猜测您希望 y 是名称的所有相关属性的总和(例如,soldTickets 对应于 "sopAdvance"),那么它可能看起来像这样(参见 cmets):

const mapWaterfallChartData = (data) => {
    // Creaet the result object with no properties or prorotype (or
    // in modern code, I'd use a `Map` instead)
    const result = Object.create(null);
    // Loop through the points
    for (const point of data) {
        // Loop through the categories
        for (const name of ["sopAdvance", "playedOff", "sales", "eopAdvance"]) {
            // Get the current category entry for this, if we have one
            let entry = result[name];
            if (!entry) {
                // We don't have one yet, create and remember a new one
                entry = result[name] = {
                    name,
                    y: 0,
                };
            }
            // Update `y` with the relevant measure
            switch (name) {
                case "sopAdvance";
                    entry.y += point.advanceTickets;
                    break;
                case "playedOff";
                    entry.y += point.playedOffTickets;
                    break;
                case "sales";
                    entry.y += point.soldTickets;
                    break;
                case "eopAdvance";
                    entry.y += point.eopAdvanceTickets;
                    break;
            }
        }
    }
    return Object.values(result);
};

但在类别数组中包含属性名称可能会很方便,因此我们不需要switch

const categories = [
    {name: "sopAdvance", prop: "advanceTickets"},
    {name: "playedOff", prop: "playedOffTickets"},
    {name: "sales", prop: "soldTickets"},
    {name: "eopAdvance", prop: "eopAdvanceTickets"},
];
const mapWaterfallChartData = (data) => {
    // Creaet the result object with no properties or prorotype (or
    // in modern code, I'd use a `Map` instead)
    const result = Object.create(null);
    // Loop through the points
    for (const point of data) {
        // Loop through the categories
        for (const {name, prop} of categories) {
            // Get the current category entry for this, if we have one
            let entry = result[name];
            if (!entry) {
                // We don't have one yet, create and remember a new one
                entry = result[name] = {
                    name,
                    y:0,
                };
            }
            // Update `y` with the relevant measure
            entry.y += point[prop];
        }
    }
    return Object.values(result);
};

现场示例:

const productMapData = [{
    "occurredAt": "2021-09-20T00:00:00.000",
    "soldTickets": 3836,
    "soldRevenue": 70762,
    "playedOffTickets": 2068,
    "playedOffRevenue": 41429.5,
    "changeInPeriodTickets": 1768,
    "changeInPeriodRevenue": 29332.5,
    "eopAdvanceTickets": 1768,
    "eopAdvanceRevenue": 29332.5,
    "advanceTickets": 1500,
    "advanceRevenue": 11521
  },
  {
    "occurredAt": "2021-09-27T00:00:00.000",
    "soldTickets": 4708,
    "soldRevenue": 88647.5,
    "playedOffTickets": 2127,
    "playedOffRevenue": 49526.5,
    "changeInPeriodTickets": 2581,
    "changeInPeriodRevenue": 39121,
    "eopAdvanceTickets": 2581,
    "eopAdvanceRevenue": 39121,
    "advanceTickets": 700,
    "advanceRevenue": 9521
  },
  {
    "occurredAt": "2021-10-04T00:00:00.000",
    "soldTickets": 5514,
    "soldRevenue": 93969.5,
    "playedOffTickets": 988,
    "playedOffRevenue": 9983,
    "changeInPeriodTickets": 4526,
    "changeInPeriodRevenue": 83986.5,
    "eopAdvanceTickets": 4526,
    "eopAdvanceRevenue": 83986.5,
    "advanceTickets": 1730,
    "advanceRevenue": 14650
  },
  {
    "occurredAt": "2021-10-11T00:00:00.000",
    "soldTickets": 7598,
    "soldRevenue": 109059.5,
    "playedOffTickets": 1476,
    "playedOffRevenue": 16474.5,
    "changeInPeriodTickets": 6122,
    "changeInPeriodRevenue": 92585,
    "eopAdvanceTickets": 6122,
    "eopAdvanceRevenue": 92585,
    "advanceTickets": 800,
    "advanceRevenue": 7560
  },
];

const categories = [
    {name: "sopAdvance", prop: "advanceTickets"},
    {name: "playedOff", prop: "playedOffTickets"},
    {name: "sales", prop: "soldTickets"},
    {name: "eopAdvance", prop: "eopAdvanceTickets"},
];
const mapWaterfallChartData = (data) => {
    // Creaet the result object with no properties or prorotype (or
    // in modern code, I'd use a `Map` instead)
    const result = Object.create(null);
    // Loop through the points
    for (const point of data) {
        // Loop through the categories
        for (const {name, prop} of categories) {
            // Get the current category entry for this, if we have one
            let entry = result[name];
            if (!entry) {
                // We don't have one yet, create and remember a new one
                entry = result[name] = {
                    name,
                    y:0,
                };
            }
            // Update `y` with the relevant measure
            entry.y += point[prop];
        }
    }
    return Object.values(result);
};

console.log(mapWaterfallChartData(productMapData));

【讨论】:

    【解决方案2】:

    这可能是我期望你想要的东西

    减少就好了。我们给出要累积的东西的列表,你会得到数组中的每个值和一个总和

    请注意,我们可以向存储桶添加更多键

    const productMapData = [{ "occurredAt": "2021-09-20T00:00:00.000", "soldTickets": 3836, "soldRevenue": 70762, "playedOffTickets": 2068, "playedOffRevenue": 41429.5, "changeInPeriodTickets": 1768, "changeInPeriodRevenue": 29332.5, "eopAdvanceTickets": 1768, "eopAdvanceRevenue": 29332.5, "advanceTickets": 1500, "advanceRevenue": 11521 }, { "occurredAt": "2021-09-27T00:00:00.000", "soldTickets": 4708, "soldRevenue": 88647.5, "playedOffTickets": 2127, "playedOffRevenue": 49526.5, "changeInPeriodTickets": 2581, "changeInPeriodRevenue": 39121, "eopAdvanceTickets": 2581, "eopAdvanceRevenue": 39121, "advanceTickets": 700, "advanceRevenue": 9521 }, { "occurredAt": "2021-10-04T00:00:00.000", "soldTickets": 5514, "soldRevenue": 93969.5, "playedOffTickets": 988, "playedOffRevenue": 9983, "changeInPeriodTickets": 4526, "changeInPeriodRevenue": 83986.5, "eopAdvanceTickets": 4526, "eopAdvanceRevenue": 83986.5, "advanceTickets": 1730, "advanceRevenue": 14650 }, { "occurredAt": "2021-10-11T00:00:00.000", "soldTickets": 7598, "soldRevenue": 109059.5, "playedOffTickets": 1476, "playedOffRevenue": 16474.5, "changeInPeriodTickets": 6122, "changeInPeriodRevenue": 92585, "eopAdvanceTickets": 6122, "eopAdvanceRevenue": 92585, "advanceTickets": 800, "advanceRevenue": 7560 }, ];
    
    // you can have more keys going to the same bucket
    const buckets = { "advanceTickets": "sopAdvance", "playedOffTickets": "playedOff", "soldTickets" : "sales",               "eopAdvanceTickets":  "eopAdvance" };
    
    const names = Object.keys(buckets);
    
    const mapWaterfallChartData = productMapData.reduce((accumulator, point) => {
      names.forEach(name => {
        const bucket = buckets[name]
        accumulator[bucket] = accumulator[bucket] || {
          data: [],
          total: 0
        };
        accumulator[bucket].data.push(point[name])
        accumulator[bucket].total += point[name]
      })
      return accumulator
    }, {});
    
    console.log(mapWaterfallChartData)

    如果没有列表,我们可以这样做:

    const productMapData = [{ "occurredAt": "2021-09-20T00:00:00.000", "soldTickets": 3836, "soldRevenue": 70762, "playedOffTickets": 2068, "playedOffRevenue": 41429.5, "changeInPeriodTickets": 1768, "changeInPeriodRevenue": 29332.5, "eopAdvanceTickets": 1768, "eopAdvanceRevenue": 29332.5, "advanceTickets": 1500, "advanceRevenue": 11521 }, { "occurredAt": "2021-09-27T00:00:00.000", "soldTickets": 4708, "soldRevenue": 88647.5, "playedOffTickets": 2127, "playedOffRevenue": 49526.5, "changeInPeriodTickets": 2581, "changeInPeriodRevenue": 39121, "eopAdvanceTickets": 2581, "eopAdvanceRevenue": 39121, "advanceTickets": 700, "advanceRevenue": 9521 }, { "occurredAt": "2021-10-04T00:00:00.000", "soldTickets": 5514, "soldRevenue": 93969.5, "playedOffTickets": 988, "playedOffRevenue": 9983, "changeInPeriodTickets": 4526, "changeInPeriodRevenue": 83986.5, "eopAdvanceTickets": 4526, "eopAdvanceRevenue": 83986.5, "advanceTickets": 1730, "advanceRevenue": 14650 }, { "occurredAt": "2021-10-11T00:00:00.000", "soldTickets": 7598, "soldRevenue": 109059.5, "playedOffTickets": 1476, "playedOffRevenue": 16474.5, "changeInPeriodTickets": 6122, "changeInPeriodRevenue": 92585, "eopAdvanceTickets": 6122, "eopAdvanceRevenue": 92585, "advanceTickets": 800, "advanceRevenue": 7560 }, ];
    
    
    const mapWaterfallChartData = productMapData.reduce((accumulator, point) => {
      Object.keys(point).forEach(name => {
        accumulator[name] = accumulator[name] || {
          data: [],
          total: 0
        };
        accumulator[name].data.push(point[name])
        if (isNaN(point[name])) {
          delete accumulator[name].total; // no need to total the dates
        }
        else {
          accumulator[name].total += point[name]
        }  
      })
      return accumulator
    }, {});
    
    console.log(mapWaterfallChartData)

    【讨论】:

      猜你喜欢
      • 2018-10-21
      • 1970-01-01
      • 2013-09-16
      • 1970-01-01
      • 2021-05-07
      • 2018-02-22
      • 1970-01-01
      • 2021-03-14
      • 1970-01-01
      相关资源
      最近更新 更多