阅读 1942

JSON数据归类的实现

前言

今天在写业务代码时,遇到了表格归类的一个需求,刚开始以为很简单,但是真正上手实现时,发现还是有一点点难度的。

本文将以上述问题为背景,讲解JSON数据归类的实现,欢迎各位感兴趣的开发者阅读本文。

问题背景

如下图所示,需要将图一的表格转成图二的表格。

实现思路

观察上图后我们发现,这个问题可以描述为:将姓名相同的数据合并到一起。

我们的解决方案为:通过数据来渲染dom。

  • 获取DOM表格内的数据将其转换为JSON
  • 对获取的表格JSON数据根据姓名字段进行归类
  • 将归类好的JSON数据重新渲染成DOM表格

实现代码

获取DOM表格内的数据将其转换为JSON,将归类好的JSON重新渲染成DOM表格不是本文的重点,所以此处不予实现。

此处重点讲解JSON数据归类的实现。

  • 将DOM表格转换成JSON后的数据如下
[
    {
        "name": "李四",
        "title": "鸡腿",
        "bookingUnit": "4",
        "measUnit": "",
        "unitPrice": "5",
        "totalPrice": "20"
    },
    {
        "name": "张三",
        "title": "牛奶",
        "bookingUnit": "5",
        "measUnit": "",
        "unitPrice": "10",
        "totalPrice": "50"
    },
    {
        "name": "李四",
        "title": "口蘑",
        "bookingUnit": "3",
        "measUnit": "",
        "unitPrice": "4",
        "totalPrice": "12"
    },
    {
        "name": "王五",
        "title": "蘑菇",
        "bookingUnit": "3",
        "measUnit": "",
        "unitPrice": "4",
        "totalPrice": "12"
    },
    {
        "name": "王五",
        "title": "牛肉",
        "bookingUnit": "13",
        "measUnit": "",
        "unitPrice": "14",
        "totalPrice": "112"
    }
]
复制代码
  • 归类好的JSON数据如下
[
  {
    "name": "李四",
    "children": [
      {
        "title": "鸡腿",
        "bookingUnit": "4",
        "measUnit": "",
        "unitPrice": "5",
        "totalPrice": "20"
      },
      {
        "title": "口蘑",
        "bookingUnit": "3",
        "measUnit": "",
        "unitPrice": "4",
        "totalPrice": "12"
      }
    ]
  },
  {
    "name": "张三",
    "children": [
      {
        "title": "牛奶",
        "bookingUnit": "5",
        "measUnit": "",
        "unitPrice": "10",
        "totalPrice": "50"
      }
    ]
  },
  {
    "name": "王五",
    "children": [
      {
        "title": "蘑菇",
        "bookingUnit": "3",
        "measUnit": "",
        "unitPrice": "4",
        "totalPrice": "12"
      },
      {
        "title": "牛肉",
        "bookingUnit": "13",
        "measUnit": "",
        "unitPrice": "14",
        "totalPrice": "112"
      }
    ]
  }
]
复制代码

实现归类函数

经过上述分析后,我们面临的问题是:将获取到DOM表格的JSON数据转换为我们最终渲染DOM需要的数据。

所以,我们要实现一个JSON归类函数,思路如下:

  • 声明一个函数,参数为一个JSON数组
  • 函数内部声明一个数组,用于存放归类好的数据
  • 函数内部声明一个对象,用于存放已经遍历过的元素。
  • 遍历传进来的JSON数组
  • 判断当前遍历到的元素是否存在于已经遍历过的元素对象中
  • 如果不存在,将当前遍历到的元素对象放进已经归类好的数组中,将当前遍历的对象放进已遍历元素对象中
  • 如果存在,遍历归类好数据,如果遍历到的元素等于当前元素对象,则将当前元素对象放进遍历到的元素children数组中,结束当前循环,继续下一轮。
  • 返回归类好的JSON数据

我们将上述思路转换为代码

/**
 * JSON归类 根据特定条件,将同类数据归类到一起
 * @param arr
 * @returns {[]}
 * @constructor
 */
const JsonClassification = (arr) => {
    // 存放最终归类好的数据
    const resultData = [];
    // 存放已经遍历过的元素
    const temp = {};
    for (let i = 0; i < arr.length; i++) {
        const item = arr[i];
        const itemObj = {
            title: item.title,
            bookingUnit: item.bookingUnit,
            measUnit: item.measUnit,
            unitPrice: item.unitPrice,
            totalPrice: item.totalPrice
        }
        // 判断当前key是否在已经遍历过的元素对象里
        if (!temp[item.name]) {
            resultData.push({
                name: item.name,
                children: [itemObj]
            });
            // 将当前key放进已经遍历过的元素对象中
            temp[item.name] = item;
        } else {
            // 遍历归类好的数据,将当前遍历到的数据放进与之对应的分类中
            for (let j = 0; j < resultData.length; j++) {
                let resultItem = resultData[j];
                if (resultItem.name === item.name) {
                    resultItem.children.push(itemObj);
                    break;
                }
            }
        }
    }
    return resultData;
}
复制代码

执行结果如下,数据满足了我们的需求,将归类好的json数据渲染成table表格就完美的解决了文章开头遇到的问题了。

更多实现方法

群友 @lipd 使用reduce实现了JSON归类函数,代码量比我的实现方式少了很多,感兴趣的开发者可以看看他的实现(如下图所示)

  • 用一行代码解决上述问题(来自复旦某研究生@Roger的解决方案)
import {compose, prop, groupBy, map, concat, pluck, flatten, toPairs, zipObj} from "ramda";

const JSONClassify = compose(map(zipObj(['name', 'children']) ) , toPairs, map(pluck('children') ) , groupBy(prop("name") ), map(({ name, ...rest }) => ({ name, children: [rest] })))

复制代码

写在最后

  • 文中如有错误,欢迎在评论区指正,如果这篇文章帮到了你,欢迎点赞和关注😊
  • 本文首发于掘金,未经许可禁止转载💌
文章分类
前端
文章标签