根据对象数组中的其他两个值将值转换为百分比

Posted

技术标签:

【中文标题】根据对象数组中的其他两个值将值转换为百分比【英文标题】:Convert values to percents based on two other values in array of objects 【发布时间】:2021-07-28 08:15:05 【问题描述】:

我有一个对象数组:

let data = [
  date:'2018-01-01', device: 'iphone',   site: 'google', val1:10, val2:20, val3:30,
  date:'2018-01-01', device: 'iphone',   site: 'bing',   val1:23, val2:12, val3:14,
  date:'2018-01-01', device: 'iphone',   site: 'jeeves', val1:67, val2:78, val3:12,
  date:'2018-01-01', device: 'ipad',     site: 'google', val1:10, val2:20, val3:30,
  date:'2018-01-01', device: 'ipad',     site: 'bing',   val1:23, val2:12, val3:14,
  date:'2018-01-01', device: 'ipad',     site: 'jeeves', val1:67, val2:78, val3:12,
  date:'2018-01-02', device: 'iphone',   site: 'google', val1:11, val2:22, val3:33,
  date:'2018-01-02', device: 'iphone',   site: 'bing',   val1:25, val2:27, val3:28,
  date:'2018-01-02', device: 'iphone',   site: 'jeeves', val1:67, val2:80, val3:15,
  date:'2018-01-02', device: 'ipad',     site: 'google', val1:12, val2:21, val3:31,
  date:'2018-01-02', device: 'ipad',     site: 'bing',   val1:26, val2:16, val3:11,
  date:'2018-01-02', device: 'ipad',     site: 'jeeves', val1:65, val2:79, val3:55,
  date:'2018-01-03', device: 'iphone',   site: 'google', val1:17, val2:19, val3:11,
  date:'2018-01-03', device: 'iphone',   site: 'bing',   val1:13, val2:15, val3:12,
  date:'2018-01-03', device: 'iphone',   site: 'jeeves', val1:69, val2:79, val3:15,
  date:'2018-01-03', device: 'ipad',     site: 'google', val1:17, val2:51, val3:31,
  date:'2018-01-03', device: 'ipad',     site: 'bing',   val1:25, val2:15, val3:17,
  date:'2018-01-03', device: 'ipad',     site: 'jeeves', val1:61, val2:71, val3:15
]

我想根据日期和设备将val1 转换为百分比。

如果设备是iphone,那么在2018-01-01 上,我希望vals 例如:val1 分别为10%23%67%

到目前为止我的代码:

let data = [
  date:'2018-01-01', device: 'iphone',   site: 'google', val1:10, val2:20, val3:30,
  date:'2018-01-01', device: 'iphone',   site: 'bing',   val1:23, val2:12, val3:14,
  date:'2018-01-01', device: 'iphone',   site: 'jeeves', val1:67, val2:78, val3:12,
  date:'2018-01-01', device: 'ipad',     site: 'google', val1:10, val2:20, val3:30,
  date:'2018-01-01', device: 'ipad',     site: 'bing',   val1:23, val2:12, val3:14,
  date:'2018-01-01', device: 'ipad',     site: 'jeeves', val1:67, val2:78, val3:12,
  date:'2018-01-02', device: 'iphone',   site: 'google', val1:11, val2:22, val3:33,
  date:'2018-01-02', device: 'iphone',   site: 'bing',   val1:25, val2:27, val3:28,
  date:'2018-01-02', device: 'iphone',   site: 'jeeves', val1:67, val2:80, val3:15,
  date:'2018-01-02', device: 'ipad',     site: 'google', val1:12, val2:21, val3:31,
  date:'2018-01-02', device: 'ipad',     site: 'bing',   val1:26, val2:16, val3:11,
  date:'2018-01-02', device: 'ipad',     site: 'jeeves', val1:65, val2:79, val3:55,
  date:'2018-01-03', device: 'iphone',   site: 'google', val1:17, val2:19, val3:11,
  date:'2018-01-03', device: 'iphone',   site: 'bing',   val1:13, val2:15, val3:12,
  date:'2018-01-03', device: 'iphone',   site: 'jeeves', val1:69, val2:79, val3:15,
  date:'2018-01-03', device: 'ipad',     site: 'google', val1:17, val2:51, val3:31,
  date:'2018-01-03', device: 'ipad',     site: 'bing',   val1:25, val2:15, val3:17,
  date:'2018-01-03', device: 'ipad',     site: 'jeeves', val1:61, val2:71, val3:15
]

//Grouping by date
const group_data = data.reduce((a, c) => 
                          (a[c['date']] = a[c['date']] || []).push(c);
                          return a;
                        , );
                    

// I am able to sum the data but not % each of them. Here I am able to group by 2 value, that is 'date' and 'device'
const grp_data = (grouped_data, first_group, second_group) => 
    for (const key of Object.keys(grouped_data)) 
        const map_data = new Map();
        for (const 
            [first_group]: date, [second_group]: device, ...other_vals
        
        of grouped_data[key]) 
            const row = map_data.get(date + ',' + device) || 
                date,
                device
            
            Object.entries(other_vals).forEach(([k, v]) => 
                if (/^[0-9,.]*$/.test(v) === true && typeof v !== 'number') v = parseFloat(v.replace(/\,/gi, ''));
                row[k] = (row[k] || 0) + v
            );
            map_data.set(date + ',' + device, row);
        
        grouped_data[key] = [...map_data.values()];
    

grp_data(group_data, 'date', 'device');

console.log(group_data);
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

虽然我可以通过 2 个键对数据进行分组,但我不确定如何将 val1 转换为 %。

我不确定如何从这里获取数据:

date:'2018-01-01', device: 'iphone',   site: 'google', val1:10%, val2:18.18%, val3:53.57%,
date:'2018-01-01', device: 'iphone',   site: 'bing',   val1:23%, val2:10.90%, val3:25%,
date:'2018-01-01', device: 'iphone',   site: 'jeeves', val1:67%, val2:70.90%, val3:21.42%,
...

【问题讨论】:

@Mr_Green,正如我在最后提到的。当日期为“2018-01-01”且设备:“iphone”时,我将所有 3 个 val1 加起来,因此为 10+23+67,然后对于谷歌来说,它使其 (10*100)/100 获得谷歌的百分比和bing 和 jeeves 等等。 10% 不是 javascript 中的有效数字。要么删除 % 符号,要么将其设为字符串。 @PalSingh 我可以删除 % 符号 您能否在您的问题中添加“2018-01-01”的第一个索引应该是什么样的?因为我不清楚你到底想要什么。 【参考方案1】:

根据你的解释,我以完全不同的方式尝试了这个。

let data = [
  date:'2018-01-01', device: 'iphone',   site: 'google', val1:10, val2:20, val3:30,
  date:'2018-01-01', device: 'iphone',   site: 'bing',   val1:23, val2:12, val3:14,
  date:'2018-01-01', device: 'iphone',   site: 'jeeves', val1:67, val2:78, val3:12,
  date:'2018-01-01', device: 'ipad',     site: 'google', val1:10, val2:20, val3:30,
  date:'2018-01-01', device: 'ipad',     site: 'bing',   val1:23, val2:12, val3:14,
  date:'2018-01-01', device: 'ipad',     site: 'jeeves', val1:67, val2:78, val3:12,
  date:'2018-01-02', device: 'iphone',   site: 'google', val1:11, val2:22, val3:33,
  date:'2018-01-02', device: 'iphone',   site: 'bing',   val1:25, val2:27, val3:28,
  date:'2018-01-02', device: 'iphone',   site: 'jeeves', val1:67, val2:80, val3:15,
  date:'2018-01-02', device: 'ipad',     site: 'google', val1:12, val2:21, val3:31,
  date:'2018-01-02', device: 'ipad',     site: 'bing',   val1:26, val2:16, val3:11,
  date:'2018-01-02', device: 'ipad',     site: 'jeeves', val1:65, val2:79, val3:55,
  date:'2018-01-03', device: 'iphone',   site: 'google', val1:17, val2:19, val3:11,
  date:'2018-01-03', device: 'iphone',   site: 'bing',   val1:13, val2:15, val3:12,
  date:'2018-01-03', device: 'iphone',   site: 'jeeves', val1:69, val2:79, val3:15,
  date:'2018-01-03', device: 'ipad',     site: 'google', val1:17, val2:51, val3:31,
  date:'2018-01-03', device: 'ipad',     site: 'bing',   val1:25, val2:15, val3:17,
  date:'2018-01-03', device: 'ipad',     site: 'jeeves', val1:61, val2:71, val3:15
]

let dataObj = ; 
data.forEach(d => 
    if(!dataObj[d.date]) dataObj[d.date] = ;
    if(!dataObj[d.date][d.device]) dataObj[d.date][d.device] = ;
    if(!dataObj[d.date][d.device].val1) dataObj[d.date][d.device].val1 = 0;
    if(!dataObj[d.date][d.device].val2) dataObj[d.date][d.device].val2 = 0;
    if(!dataObj[d.date][d.device].val3) dataObj[d.date][d.device].val3 = 0;
    dataObj[d.date][d.device].val1 += d.val1;
    dataObj[d.date][d.device].val2 += d.val2;
    dataObj[d.date][d.device].val3 += d.val3;
);

data.forEach(d => 
  d.val1 = d.val1 * 100 / dataObj[d.date][d.device].val1;
  d.val2 = d.val2 * 100 / dataObj[d.date][d.device].val2;
  d.val3 = d.val3 * 100 / dataObj[d.date][d.device].val3;
);

console.log(data);

【讨论】:

以上是关于根据对象数组中的其他两个值将值转换为百分比的主要内容,如果未能解决你的问题,请参考以下文章

如何根据javascript中的键合并和替换两个数组中的对象?

循环遍历Vue.js中的动态数组,然后根据对应的值将每个对象组件添加到单独组件中的div中?

根据键中的子字符串将对象转换为对象数组

根据 NSDictionary 键值将 NSArray 拆分为子数组

mySQL中的JSON操作

Javascript将数组转换为对象数组