字符串压缩(二)之LZ4

news/2024/5/17 15:20:23/文章来源:https://blog.csdn.net/jh035512/article/details/128090609

一、LZ4压缩与解压

  LZ4有两个压缩函数。默认压缩函数原型:

  int LZ4_compress_default(const char* src, char* dst, int srcSize, int dstCapacity);

  快速压缩函数原型:

  int LZ4_compress_fast (const char* src, char* dst, int srcSize, int dstCapacity, int acceleration);

  快速压缩函数acceleration的参数范围:[1 ~ LZ4_ACCELERATION_MAX],其中LZ4_ACCELERATION_MAX为65537。什么意思呢,简单的说就是acceleration值越大,压缩速率越快,但是压缩比就越低,后面我会用实验数据来进行说明。

  另外,当acceleration = 1时,就是简化版的LZ4_compress_defaultLZ4_compress_default函数默认acceleration = 1。

  LZ4也有两个解缩函数。安全解缩函数原型:

  int LZ4_decompress_safe (const char* src, char* dst, int compressedSize, int dstCapacity);

  快速解缩函数原型:
  int LZ4_decompress_fast (const char* src, char* dst, int originalSize);

  快速解压函数不建议使用。因为LZ4_decompress_fast 缺少被压缩后的文本长度参数,被认为是不安全的,LZ4建议使用LZ4_decompress_safe。

  同样,我们先来看看LZ4的压缩与解压缩示例。

 1 #include <stdio.h>2 #include <string.h>3 #include <sys/time.h>4 #include <malloc.h>5 #include <lz4.h>6 #include <iostream>7 8 using namespace std;9 
10 int main()
11 {
12     char peppa_pig_buf[2048] = "Narrator: It is raining today. So, Peppa and George cannot \
13     play outside.Peppa: Daddy, it's stopped raining. Can we go out to play?Daddy: Alright, \
14     run along you two.Narrator: Peppa loves jumping in muddy puddles.Peppa: I love muddy puddles.\
15     Mummy: Peppa. If you jumping in muddy puddles, you must wear your boots.Peppa: Sorry, Mummy.\
16     Narrator: George likes to jump in muddy puddles, too.Peppa: George. If you jump in muddy \
17     puddles, you must wear your boots.Narrator: Peppa likes to look after her little brother, \
18     George.Peppa: George, let's find some more pud dles.Narrator: Peppa and George are having \
19     a lot of fun. Peppa has found a lttle puddle. George hasfound a big puddle.Peppa: Look, \
20     George. There's a really big puddle.Narrator: George wants to jump into the big puddle first.\
21     Peppa: Stop, George. | must check if it's safe for you. Good. It is safe for you. \
22     Sorry, George. It'sonly mud.Narrator: Peppa and George love jumping in muddy puddles.\
23     Peppa: Come on, George. Let's go and show Daddy.Daddy: Goodness me.Peppa: Daddy. Daddy. \
24     Guess what we' ve been doing.Daddy: Let me think... Have you been wa tching television?\
25     Peppa: No. No. Daddy.Daddy: Have you just had a bath?Peppa: No. No.Daddy: | know. \
26     You've been jumping in muddy puddles.Peppa: Yes. Yes. Daddy. We've been jumping in muddy \
27     puddles.Daddy: Ho. Ho. And look at the mess you're in.Peppa: Oooh....Daddy: Oh, well, \
28     it's only mud. Let's clean up quickly before Mummy sees the mess.Peppa: Daddy, \
29     when we've cleaned up, will you and Mummy Come and play, too?Daddy: Yes, we can all play \
30     in the garden.Narrator: Peppa and George are wearing their boots. Mummy and Daddy are \
31     wearing their boots.Peppa loves jumping up and down in muddy puddles. Everyone loves jumping \
32     up and down inmuddy puddles.Mummy: Oh, Daddy pig, look at the mess you're in. .Peppa: \
33     It's only mud.";
34 
35     size_t com_space_size;
36     size_t peppa_pig_text_size;
37 
38     char *com_ptr = NULL;
39 
40     // compress
41     peppa_pig_text_size = strlen(peppa_pig_buf);
42     com_space_size = LZ4_compressBound(peppa_pig_text_size);
43     
44     com_ptr = (char *)malloc(com_space_size);
45     if(NULL == com_ptr) {
46         cout << "compress malloc failed" << endl;
47         return -1;
48     }
49 
50     memset(com_ptr, 0, com_space_size);
51 
52     size_t com_size;
53     //com_size = LZ4_compress_default(peppa_pig_buf, com_ptr, peppa_pig_text_size, com_space_size);
54     com_size = LZ4_compress_fast(peppa_pig_buf, com_ptr, peppa_pig_text_size, com_space_size, 1);
55     cout << "peppa pig text size:" << peppa_pig_text_size << endl;
56     cout << "compress text size:" << com_size << endl;
57     cout << "compress ratio:" << (float)peppa_pig_text_size / (float)com_size << endl << endl;
58 
59 
60     // decompress
61     size_t decom_size;
62     char* decom_ptr = NULL;
63     
64     decom_ptr = (char *)malloc((size_t)peppa_pig_text_size);
65     if(NULL == decom_ptr) {
66         cout << "decompress malloc failed" << endl;
67         return -1;
68     }
69 
70     decom_size = LZ4_decompress_safe(com_ptr, decom_ptr, com_size, peppa_pig_text_size);
71     cout << "decompress text size:" << decom_size << endl;
72 
73     // use decompress buf compare with origin buf
74     if(strncmp(peppa_pig_buf, decom_ptr, peppa_pig_text_size)) {
75         cout << "decompress text is not equal peppa pig text" << endl;
76     }
77     
78     free(com_ptr);
79     free(decom_ptr);
80     return 0;
81 }

执行结果:

  从结果可以发现,压缩之前的peppa pig文本长度为1848,压缩后的文本长度为1125(上一篇ZSTD为759),压缩率为1.6,解压后的长度与压缩前相等。相同文本情况下,压缩率低于ZSTD的2.4。从文本被压缩后的长度表现来说,LZ4比ZSTD要差。

  下图图1是LZ4随着acceleration的递增,文本被压缩后的长度与acceleration的关系。随着acceleration的递增,文本被压缩后的长度越来越长。

图1

  图2是LZ4随着acceleration的递增,压缩率与acceleration的关系。随着acceleration的递增,压缩率也越来越低。

 图2

  这是为什么呢?还是上一篇提到的 鱼(性能)和熊掌(压缩比)的关系。获得了压缩的高性能,失去了算法的压缩率。

二、LZ4压缩性能探索

  接下来摸索一下LZ4的压缩性能,以及LZ4在不同acceleration级别下的压缩性能。

  测试方法是,使用LZ4_compress_fast,连续压缩同一段文本并持续10秒。每一次分别使用不同的acceleration级别,最后得到每一种acceleration级别下每秒的平均压缩速率。测试压缩性能的代码示例如下:

 1 #include <stdio.h>2 #include <string.h>3 #include <sys/time.h>4 #include <malloc.h>5 #include <lz4.h>6 #include <iostream>7 8 using namespace std;9 
10 int main()
11 {
12     char peppa_pig_buf[2048] = "Narrator: It is raining today. So, Peppa and George cannot \
13     play outside.Peppa: Daddy, it's stopped raining. Can we go out to play?Daddy: Alright, \
14     run along you two.Narrator: Peppa loves jumping in muddy puddles.Peppa: I love muddy puddles.\
15     Mummy: Peppa. If you jumping in muddy puddles, you must wear your boots.Peppa: Sorry, Mummy.\
16     Narrator: George likes to jump in muddy puddles, too.Peppa: George. If you jump in muddy \
17     puddles, you must wear your boots.Narrator: Peppa likes to look after her little brother, \
18     George.Peppa: George, let's find some more pud dles.Narrator: Peppa and George are having \
19     a lot of fun. Peppa has found a lttle puddle. George hasfound a big puddle.Peppa: Look, \
20     George. There's a really big puddle.Narrator: George wants to jump into the big puddle first.\
21     Peppa: Stop, George. | must check if it's safe for you. Good. It is safe for you. \
22     Sorry, George. It'sonly mud.Narrator: Peppa and George love jumping in muddy puddles.\
23     Peppa: Come on, George. Let's go and show Daddy.Daddy: Goodness me.Peppa: Daddy. Daddy. \
24     Guess what we' ve been doing.Daddy: Let me think... Have you been wa tching television?\
25     Peppa: No. No. Daddy.Daddy: Have you just had a bath?Peppa: No. No.Daddy: | know. \
26     You've been jumping in muddy puddles.Peppa: Yes. Yes. Daddy. We've been jumping in muddy \
27     puddles.Daddy: Ho. Ho. And look at the mess you're in.Peppa: Oooh....Daddy: Oh, well, \
28     it's only mud. Let's clean up quickly before Mummy sees the mess.Peppa: Daddy, \
29     when we've cleaned up, will you and Mummy Come and play, too?Daddy: Yes, we can all play \
30     in the garden.Narrator: Peppa and George are wearing their boots. Mummy and Daddy are \
31     wearing their boots.Peppa loves jumping up and down in muddy puddles. Everyone loves jumping \
32     up and down inmuddy puddles.Mummy: Oh, Daddy pig, look at the mess you're in. .Peppa: \
33     It's only mud.";
34 
35     int cnt = 0;
36     
37     size_t com_size;
38     size_t com_space_size;
39     size_t peppa_pig_text_size;
40 
41     timeval st, et;
42     char *com_ptr = NULL;
43 
44     peppa_pig_text_size = strlen(peppa_pig_buf);
45     com_space_size = LZ4_compressBound(peppa_pig_text_size);
46 
47     int test_times = 6;
48     int acceleration = 1;
49     
50     // compress performance test
51     while(test_times >= 1) {
52     
53         gettimeofday(&st, NULL);
54         while(1) {
55         
56             com_ptr = (char *)malloc(com_space_size);
57             if(NULL == com_ptr) {
58                 cout << "compress malloc failed" << endl;
59                 return -1;
60             }
61             
62             com_size = LZ4_compress_fast(peppa_pig_buf, com_ptr, peppa_pig_text_size, com_space_size, acceleration);
63             if(com_size <= 0) {
64                 cout << "compress failed, error code:" << com_size << endl;
65                 free(com_ptr);
66                 return -1;
67             }
68             
69             free(com_ptr);
70         
71             cnt++;
72             gettimeofday(&et, NULL);
73             if(et.tv_sec - st.tv_sec >= 10) {
74                 break;
75             }
76         }
77         
78         cout << "acceleration:" << acceleration << ", compress per second:" << cnt/10 << " times" << endl;
79 
80         ++acceleration;
81         --test_times;
82     }
83 
84     return 0;
85 }

执行结果:

 

  结果可以总结为两点:一是acceleration为默认值1时,即LZ4_compress_default函数的默认值时,每秒的压缩性能在20W+;二是随着acceleration的递增,每秒的压缩性能也在递增,但是代价就是获得更低的压缩率。

  acceleration递增与压缩速率的关系如下图所示:

 图3

三、LZ4解压性能探索

  接下来继续了解一下LZ4的解压性能。

  测试方法是先使用LZ4_compress_fastacceleration = 1压缩文本,再使用安全解压函数LZ4_decompress_safe,连续解压同一段文本并持续10秒,最后得到每秒的平均解压速率。测试解压性能的代码示例如下:

 1 #include <stdio.h>2 #include <string.h>3 #include <sys/time.h>4 #include <malloc.h>5 #include <lz4.h>6 #include <iostream>7 8 using namespace std;9 
10 int main()
11 {
12     char peppa_pig_buf[2048] = "Narrator: It is raining today. So, Peppa and George cannot \
13     play outside.Peppa: Daddy, it's stopped raining. Can we go out to play?Daddy: Alright, \
14     run along you two.Narrator: Peppa loves jumping in muddy puddles.Peppa: I love muddy puddles.\
15     Mummy: Peppa. If you jumping in muddy puddles, you must wear your boots.Peppa: Sorry, Mummy.\
16     Narrator: George likes to jump in muddy puddles, too.Peppa: George. If you jump in muddy \
17     puddles, you must wear your boots.Narrator: Peppa likes to look after her little brother, \
18     George.Peppa: George, let's find some more pud dles.Narrator: Peppa and George are having \
19     a lot of fun. Peppa has found a lttle puddle. George hasfound a big puddle.Peppa: Look, \
20     George. There's a really big puddle.Narrator: George wants to jump into the big puddle first.\
21     Peppa: Stop, George. | must check if it's safe for you. Good. It is safe for you. \
22     Sorry, George. It'sonly mud.Narrator: Peppa and George love jumping in muddy puddles.\
23     Peppa: Come on, George. Let's go and show Daddy.Daddy: Goodness me.Peppa: Daddy. Daddy. \
24     Guess what we' ve been doing.Daddy: Let me think... Have you been wa tching television?\
25     Peppa: No. No. Daddy.Daddy: Have you just had a bath?Peppa: No. No.Daddy: | know. \
26     You've been jumping in muddy puddles.Peppa: Yes. Yes. Daddy. We've been jumping in muddy \
27     puddles.Daddy: Ho. Ho. And look at the mess you're in.Peppa: Oooh....Daddy: Oh, well, \
28     it's only mud. Let's clean up quickly before Mummy sees the mess.Peppa: Daddy, \
29     when we've cleaned up, will you and Mummy Come and play, too?Daddy: Yes, we can all play \
30     in the garden.Narrator: Peppa and George are wearing their boots. Mummy and Daddy are \
31     wearing their boots.Peppa loves jumping up and down in muddy puddles. Everyone loves jumping \
32     up and down inmuddy puddles.Mummy: Oh, Daddy pig, look at the mess you're in. .Peppa: \
33     It's only mud.";
34 
35     int cnt = 0;
36     
37     size_t com_size;
38     size_t com_space_size;
39     size_t peppa_pig_text_size;
40 
41     timeval st, et;
42     char *com_ptr = NULL;
43 
44     // compress
45     peppa_pig_text_size = strlen(peppa_pig_buf);
46     com_space_size = LZ4_compressBound(peppa_pig_text_size);
47 
48     com_ptr = (char *)malloc(com_space_size);
49     if(NULL == com_ptr) {
50         cout << "compress malloc failed" << endl;
51         return -1;
52     }
53 
54     com_size = LZ4_compress_fast(peppa_pig_buf, com_ptr, peppa_pig_text_size, com_space_size, 1);
55     if(com_size <= 0) {
56         cout << "compress failed, error code:" << com_size << endl;
57         free(com_ptr);
58         return -1;
59     }
60 
61     // decompress
62     size_t decom_size;
63     char* decom_ptr = NULL;
64     
65     // decompress performance test
66     gettimeofday(&st, NULL);
67     while(1) {
68 
69         decom_ptr = (char *)malloc((size_t)peppa_pig_text_size);
70         if(NULL == decom_ptr) {
71             cout << "decompress malloc failed" << endl;
72             free(com_ptr);
73             return -1;
74         }
75         
76         decom_size = LZ4_decompress_safe(com_ptr, decom_ptr, com_size, peppa_pig_text_size);
77         if(decom_size <= 0) {
78             cout << "decompress failed, error code:" << decom_size << endl;
79             free(com_ptr);
80             free(decom_ptr);
81             return -1;
82         }
83 
84         free(decom_ptr);
85 
86         cnt++;
87         gettimeofday(&et, NULL);
88         if(et.tv_sec - st.tv_sec >= 10) {
89             break;
90         }
91     }
92 
93     free(com_ptr);
94     cout << "decompress per second:" << cnt/10 << " times" << endl;
95     
96     return 0;
97 }

执行结果:

   结果显示LZ4的解压性能大概在每秒54W次左右,解压速率还是非常可观。

四、LZ4对比ZSTD

  使用相同的待压缩文本,分别使用ZSTD与LZ4进行压缩、解压、压缩性能、解压性能测试后有表1的数据。

表1

  

  抛开算法的优劣对比,从实验结果来看,ZSTD更加侧重于压缩率,LZ4(acceleration = 1)更加侧重于压缩性能。

五、总结

  无论任何算法,都很难做到既有高性能压缩的同时,又有特别高的压缩率。两者必须要做一个取舍,或者找到一个合适的平衡点。

  如果在性能可以接受的情况下,选择具有更高压缩率的ZSTD将更加节约存储空间(通过线程池进行多线程压缩可以进一步提升性能);如果对压缩率不是特别看中,追求更高的压缩性能,那LZ4也是一个不错的选择。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.luyixian.cn/news_show_227307.aspx

如若内容造成侵权/违法违规/事实不符,请联系dt猫网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

如何用潜类别混合效应模型(Latent Class Mixed Model ,LCMM)分析老年痴呆年龄数据

全文下载链接&#xff1a;http://tecdat.cn/?p24647线性混合模型假设 N 个受试者的群体是同质的&#xff0c;并且在群体水平上由独特的曲线 Xi(t)β 描述&#xff08;点击文末“阅读原文”获取完整代码数据&#xff09;。相关视频背景和定义相比之下&#xff0c;潜在类别混合模…

【毕业设计】24-基于单片机的电子显示屏的设计与应用(原理图+源码+仿真工程+论文+答辩PPT)

【毕业设计】24-基于单片机的电子显示屏的设计与应用&#xff08;原理图源码仿真工程论文答辩PPT&#xff09; 文章目录任务书设计说明书摘要设计框架架构设计说明书及设计文件源码展示任务书 主要研究内容&#xff1a; 通过查阅资料&#xff0c;掌握单片机基本工作原理&#…

【STM32备忘录】二、FSMC做LCD控制器,使用stm32cube配置示例

文章目录1. FSMC框图2. 配置示例(1) cube配置(2) 代码参考*疑问1. FSMC框图 如果屏幕接口8位数据宽度访问&#xff0c;地址线FSMC_A[25:0], 一共26位&#xff0c;一个块22667108864Byte64MB&#xff0c;如果屏幕接口16位数据宽度访问&#xff0c;地址线FSMC_A[25:0], 一共26位&…

鸿蒙全量源代码在线阅读

目录 前言 下载方式复杂 占用空间大 搜索效率低 本项目目标 服务器地址 使用手册 源码浏览服务 标识符搜索 普通文本搜索 代码比较 写在最后 前言 当前&#xff0c;OpenHarmony项目持续发展&#xff0c;其代码量已经超过了20G字节的存储占用空间&#xff0c;对于一…

基于人工蜂群算法的线性规划求解matlab程序

基于人工蜂群算法的线性规划求解matlab程序 1 人工蜂群算法概述 2005年D. Karaboga教授仿照蜜蜂集群采蜜生物行为&#xff0c;提出了人工蜂群仿生算法&#xff0c;可以有效解决有关函数优化等相关难题。ABC算法仿照蜜蜂蜂群中不同蜂种相互协作&#xff0c;蜂群间进行角色转换的…

不同类型的 SSL 证书解释

了解不同类型的 SSL 证书&#xff1a;扩展验证 (EV)、组织验证 (OV) 和域名验证 (DV)。 查看用例及更多。 SSL/TLS 证书用于验证网站的身份并在服务器和浏览器之间创建安全连接。有许多不同类型的 SSL 证书选项可用&#xff0c;它们都有其独特的用例和价值主张。证书颁发机构 …

电磁仿真设计RMxprt-6p72s电励磁凸极同步电机分析案例

作者 | 电机设计青年 仿真秀专栏作者 导读&#xff1a;大家好&#xff0c;我是仿真秀专栏作者——电机设计青年&#xff0c;曾担任ANSYS低频电磁工程师一职&#xff0c;后入职电机企业&#xff0c;一直从事电机产品研发工作。研究的电机类型涉及电励磁同步电机、永磁同步电机、…

MIT发现语言模型内的事实知识可被修改??

文 | 小伟前言众所周知&#xff0c;自回归语言模型(如GPT-2)里存储着大量的事实知识&#xff0c;比如语言模型可以正确的预测出埃菲尔铁塔所在的城市是巴黎市。那么语言模型是在什么地方存储这些知识呢&#xff1f;我们是否可以修改存储在语言模型里的知识呢&#xff1f;来自于…

R语言分布滞后非线性模型(DLNM)研究发病率,死亡率和空气污染示例

全文下载链接&#xff1a;http://tecdat.cn/?p21317本文提供了运行分布滞后非线性模型的示例&#xff0c;同时描述了预测变量和结果之间的非线性和滞后效应&#xff0c;这种相互关系被定义为暴露-滞后-反应关联&#xff08;点击文末“阅读原文”获取完整代码数据&#xff09;。…

[附源码]计算机毕业设计springboot本地助农产品销售系统

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

小程序上新(2022.11.15~11.28)

20221115 小程序基础库 2.27.3 更新 更新 框架 设备 VoIP 能力授权更新 框架 支持 worker 代码打包到小程序&小游戏分包 详情更新 组件 scroll-view 接近全屏尺寸时默认开启点击回到顶部更新 API createVKSession 在不需要用到摄像头的时候不再发起摄像头授权 详情修复 框…

【笔试强训】Day 4

&#x1f308;欢迎来到笔试强训专栏 (꒪ꇴ꒪(꒪ꇴ꒪ )&#x1f423;,我是Scort目前状态&#xff1a;大三非科班啃C中&#x1f30d;博客主页&#xff1a;张小姐的猫~江湖背景快上车&#x1f698;&#xff0c;握好方向盘跟我有一起打天下嘞&#xff01;送给自己的一句鸡汤&#x…

王道考研——操作系统(第三章 内存管理)

一、内存的基础知识 什么是内存&#xff1f;有何作用&#xff1f; 这么做的原因是&#xff0c;程序本来是放在外存中的&#xff0c;放在磁盘中的&#xff0c;但是磁盘的读写速度很慢&#xff0c;而cpu的处理速度又很快 存储单元就是存放数据的最小单元&#xff0c;每一个地址…

NetCore路由的Endpoint模式

IdentityServer里有各种Endpoint,如TokenEndpoint,UserInfoEndpoint,Authorize Endpoint,Discovery Endpoint等等。Endpoint从字面意思来看是“终端节点"或者“终节点”的意思。无独有偶NetCore的路由也有Endpoint的概念。那么我们提出一个问题来&#xff0c;究竟什么是En…

不用ps怎么修改图片?电脑图片在线处理的方法

很多小伙伴在工作、学习的时候会用到简单的图片处理工具&#xff08;在线ps 图片编辑制作工具 免费照片编辑器_压缩图&#xff09;&#xff0c;但是因为用到的功能比较多&#xff0c;需要下载安装很多电脑处理图片软件&#xff0c;非常不方便&#xff0c;而且上手比较难。下面就…

Windows OpenGL ES 图像色彩替换

目录 一.OpenGL ES 图像色彩替换 1.原始图片2.效果演示 二.OpenGL ES 图像色彩替换源码下载三.猜你喜欢 零基础 OpenGL ES 学习路线推荐 : OpenGL ES 学习目录 >> OpenGL ES 基础 零基础 OpenGL ES 学习路线推荐 : OpenGL ES 学习目录 >> OpenGL ES 特效 零基础 …

代码调优?从Fibonacci数列的7种写法说起,看完coding能力上一个台阶

开启掘金成长之旅&#xff01;这是我参与「掘金日新计划 12 月更文挑战」的第2天&#xff0c;点击查看活动详情 引子 楼梯有 N阶&#xff0c;上楼可以一步上一阶&#xff0c;也可以一步上二阶。 编一个程序&#xff0c;计算共有多少种不同的走法。 例&#xff1a; 0层&…

【微信小程序高频面试题——精选一】

微信小程序高频面试题小程序中如何进行接口请求&#xff1f;会不会跨域&#xff0c;为什么小程序的常用命令有哪些你认为微信小程序的优点是什么&#xff0c;缺点是什么微信小程序中的js和浏览器中的js以及node中的js的区别微信小程序中的数据渲染浏览器中有什么不同小程序中如…

FineReport表格软件- 计算操作符说明

1. 概述 FineReport 中使用函数需要用到很多的操作符。 操作符不仅包含很多运算符&#xff0c;还包括一些报表特有的操作符。 FineReport 11.0 优化了公式 2. 运算符类型 运算符用于指定要对公式中的元素执行的计算类型。有默认计算顺序&#xff0c;但可以使用括号更改此顺序…

python如何将日期字符串格式化年月日

今天用Python的DataFrame处理数据时&#xff0c;相对一波数据按日期分组处理&#xff0c;但是原始数据包含时间分秒&#xff0c;无法按日期分组&#xff0c;因此需要先将数据转成只包含年月日的数据格式。但是写代码处理过程中发现有点绕&#xff0c;不熟悉的同学容易绕晕。这种…