【问题标题】:JavaScript to split data and calculate sums用于拆分数据和计算总和的 JavaScript
【发布时间】:2017-08-11 08:29:44
【问题描述】:

我相信我需要的是两个 JavaScript 函数。我收到一个逗号分隔的字符串,其中包含两种类型的数据:1)设备名称后跟 2)数值。这两个值用逗号分隔,每个集合也用逗号分隔。下面的示例字符串:

Device_A,5,Device_C,2,Device_A,10,Device_B,8,Device_B,2,Device_C,7

我想做的是创建两个独立的函数。第一个函数查找唯一的设备名称并仅返回逗号分隔字符串中的名称。第二个函数将计算每个设备的数值之和。上面示例字符串的预期结果将返回:

功能1(设备列表):

Device_A, Device_B, Device_C

函数 2(每个设备列表的总和):

15,10,9

只要它们都匹配,列表就不需要以任何特定的顺序返回。在这一点上,我成功完成的只是返回一个唯一值列表(包括数值)......我坚持分离列表,但仍然引用设备名称来总结所有值。

提前致谢。如果您有任何问题,请告诉我! 马特

【问题讨论】:

    标签: javascript arrays string split


    【解决方案1】:

    您可以使用一个对象来收集名称和计数。

    此编辑包含一个共享函数和两个函数,结果顺序相同。

    function getGrouped(data) {
        var array = data.split(','),
            temp = Object.create(null),
            i = 0;
        
        while (i < array.length) {
            temp[array[i]] = (temp[array[i]] || 0) + +array[i + 1] || 0;
            i += 2;
        }
        return temp;
    }
    
    function getDevices(data) {
        var temp = getGrouped(data);
        return Object.keys(temp).sort().join();
    }
    
    function getCounts(data) {
        var temp = getGrouped(data);
        return Object.keys(temp).sort().map(function (k) { return temp[k]; }).join();
    }
    
    var data = "Device_A,5,Device_C,2,Device_A,10,Device_B,8,Device_B,2,Device_C,7";
    
    console.log(getDevices(data));
    console.log(getCounts(data));

    【讨论】:

    • 我尝试调整此代码,但我不断收到断言错误。 “为 :15 生成字节码失败”。我不是专家,但显然这意味着未启用断言?
    • 你从哪里得到eval
    • 这就是错误消息中的内容。脚本中没有 eval() 函数。我正在使用要求非常具体的格式的软件。我相信它希望函数中的语句在脚本末尾调用该函数。这能回答你的问题吗?
    【解决方案2】:

    当开始处理这样的问题时,我认为一开始不要担心在单个循环或花哨的单行中执行它是明智的。

    A) 首先定义您需要哪些数据结构以及如何从一种格式转换为另一种格式:

    • 将我的数据字符串转换为键和值列表
    • 以某种方式根据键对这些键和值进行分组
    • 对每个组的值求和
    • 返回所有唯一键的列表
    • 返回所有求和值的列表

    B) 然后,尝试查看您编写的任何代码是否有可能被应用程序的其他部分重用并相应地重构。

    C) 最后,评估是否存在性能瓶颈,如果存在,则针对性能进行优化。

    A.每一步都有一个函数:

    // 1. From string to array of keys and values
    // You already figured this one out. Split by ","!
    const namesAndValuesFromString =
      str => str.split(",");
      
    // 2. Grouping by key
    // Let's first make pairs:
    const deviceValuePairs = devicesAndValues => { 
      let pair = [];
      const pairs = [];
      
      devicesAndValues.forEach(x => {
        pair.push(x);
        if (pair.length === 2) {
          pairs.push(pair);
          pair = [];
        }
      });
      
      return pairs;
    };
    
    // Key value pairs are a nice starting point for constructing a grouped object:
    const kvpsToDeviceValuesObj = kvps => {
      const valuesByDevice = {};
      
      kvps.forEach(([key, value]) => {
        value = Number(value);
        
        if (!valuesByDevice[key]) {
          valuesByDevice[key] = [];
        }
        
        valuesByDevice[key].push(value);
      });
      
      return valuesByDevice;
    };
    
    // 3. Now, we can get to summing the values arrays
    const sumValueArrays = valuesByDevice => {
      const summedValuesByDevice = {};
      
      // Loop over the objects entries
      Object.entries(valuesByDevice).forEach(
        ([key, values]) => {
          summedValuesByDevice[key] = values
            .reduce((a, b) => a + b);
        }
      );
      
      return summedValuesByDevice;
    };
    
    // 4. + 5. Now that we have an object with device ids as keys, and summed values inside, we can retrieve the two lists
    const getDevices = Object.keys;
    const getSums = Object.values;
    
    // Running the code:
    const namesAndValues =
      namesAndValuesFromString("A,5,C,2,A,10,B,8,B,2,C,7");
    console.log(namesAndValues);
    
    const kvps = deviceValuePairs(namesAndValues);
    console.log(kvps);
    
    const valuesByDevice = kvpsToDeviceValuesObj(kvps);
    console.log(valuesByDevice);
    
    const sumValues = sumValueArrays(valuesByDevice);
    console.log(sumValues);
    
    const devices = getDevices(sumValues);
    console.log(devices);
    
    const sums = getSums(sumValues);
    console.log(sums);

    B.重构!

    一旦您了解了这些步骤中的每一个,您就会开始看到可以概括或组合的东西。这就是乐趣开始的地方:)

    // UTILITIES
    const split = del => arr => arr.split(del);
    const toPairs = arr => {
      let pair = [];
      
      return arr.reduce(
        (pairs, x) => {
          pair.push(x);
          if (pair.length === 2) {
            pairs.push(pair);
            pair = [];
          }
          
          return pairs;
        }, []);
    };
    
    const sum = (x, y = 0) => +x + y;
    
    const kvpsToGroups = grouper => kvps =>
      kvps.reduce(
        (groups, [key, value]) => Object.assign(groups, {
          [key]: grouper(value, groups[key])
        }), {});
    
    
    // YOUR APP
    const sumGrouper = kvpsToGroups(sum);
    const dataSplitter = split(",");
    
    const parseData = str => sumGrouper(toPairs(dataSplitter(str)));
    
    // MAIN
    const result = parseData("A,5,C,2,A,10,B,8,B,2,C,7");
    console.log("devices:", Object.keys(result));
    console.log("sums:", Object.values(result));

    【讨论】:

    • 我可以按照您的说明进行操作。但是,将其插入我们的软件时出现以下错误:“期望一个操作数,但找到了 const。”在进一步研究之后,我看起来好像我们正在使用Project Nashorn。你认为没有 const 可以做到这一点吗?
    • 您可以用常规的 var 声明替换所有常量,没有问题。错误听起来可能是另一个语法错误...
    • 你的猜测和我的一样好。我将所有常量更改为常规变量,但现在我得到了,“javax.script.ScriptException: :9:6 Expected : but found pair” 它指的是 let pair = [];行。
    【解决方案3】:

    regexs的另一种方式

    let str = "Device_A,5,Device_C,2,Device_A,10,Device_B,8,Device_B,2,Device_C,7", obj = {}
    str.match(/(\w+,[0-9]+)/g).forEach((s) => {
    	s = s.split(',')
    	obj[s[0]] = (obj[s[0]] || 0) + (Number(s[1]) || 0)
    })
    console.log(obj)

    【讨论】:

      【解决方案4】:

      应该这样做:

      var input = "Device_A,5,Device_C,2,Device_A,10,Device_B,8,Device_B,2,Device_C,7";
      
      var output = input.split(',').reduce((accumulator, currentValue, currentIndex, array) => {
      	accumulator[currentValue] = (accumulator[currentValue] || 0) 
          + parseInt(array[currentIndex + 1]);
      	array.splice(0,1);
      	return accumulator;
      }, {});
      
      console.log(Object.keys(output));
      console.log(Object.keys(output).map(k => output[k]));

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-12-13
        • 1970-01-01
        • 1970-01-01
        • 2019-05-25
        • 1970-01-01
        相关资源
        最近更新 更多