1.?视频视频?Ƶȥ??Դ??
2.七爪源码:LeetCode - 从排序列表中删除重复项
3.Nginx源码导读:[3]Ngnix头文件处理
4.PHP7源码之array_unique函数分析
5.通过深挖Clickhouse源码,我精通了数据去重!去重去重
6.降低代码的源码源码圈复杂度——复杂代码解决之道
??Ƶȥ??Դ??
讨论C#数据去重的常见方式,每种方法有其特点与适用场景,视频视频选择最合适的去重去重策略至关重要。欢迎在评论区分享更多有效数据去重方法。源码源码教育培训小程序源码出售
使用HashSet进行去重,视频视频它确保元素唯一,去重去重添加重复值时被忽略,源码源码实现高效数据去重。视频视频
Linq的去重去重Distinct()方法提供简单高效去重,基于元素相等性筛选出不重复元素,源码源码底层利用HashSet实现。视频视频
借助Linq的去重去重GroupBy()方法,根据指定键或条件对集合元素进行分组,源码源码通过选择每个分组的第一个元素实现去重。
采用自定义比较器与循环遍历实现直接去重,具体示例源码可参考github链接。
七爪源码:LeetCode - 从排序列表中删除重复项
问题描述:给定一个已排序的链表,目标是删除其中所有重复的节点,只保留每个数字的首次出现,然后返回处理后的有序链表。 示例1:删除重复的节点,例如给定链表1->1->2,结果为1->2。linuxfind命令源码 示例2:处理复杂边缘情况,如给定链表1->1->2->3->3,结果应为1->2->3。 解决方案策略:使用哈希映射:遍历链表,将节点值作为哈希键,记录出现次数。只保留出现一次的节点,时间复杂度O(N),空间复杂度O(N)。
哨兵节点:利用哨兵头节点,处理重复子列表时的边界情况。遍历链表,比较节点值和下一个节点,时间复杂度O(N),空间复杂度O(1)。
以下是不同编程语言的实现:C++代码示例
(C++代码略)
Golang代码示例
(Golang代码略)
Javascript代码示例
(Javascript代码略)
通过以上算法,我们能够有效地处理并返回一个去重后的有序链表。测试后,算法表现良好。Nginx源码导读:[3]Ngnix头文件处理
这节主要讲一下nginx , 对头文件的包含 ,怎么处理多次包含的 ,其实也可以是小的C语言知识点
在nginx中有很多头文件 ngx_core.h ngx_errno.h 等等, 并且他们很多相互包含了 ,愚蠢指标源码大家可能会想那不是有重复定义了很多数据结构吗 ?
回答是当然不是,还记得上一节中的头文件吗 ,在这我们也拿过来 , ngx_config.h : #ifndef _NGX_CONFIG_H_INCLUDED_ #define _NGX_CONFIG_H_INCLUDED_ #include "ngx_linux_config.h" typedef intptr_t ngx_int_t; typedef uintptr_t ngx_uint_t; typedef intptr_t ngx_flag_t; #endif 发现了吗 , nginx开头都有 #ifndef XXXXX ,nginx就是用这个条件宏来去重的 ,如果第一次就会#define_NGX_CONFIG_H_INCLUDED_ ,以后某个文件在include这个头文件 ,#ifndef _NGX_CONFIG_H_INCLUDED_ 这个判断就是false了,直接就都#endif了
#ifndef这个语法是预处理执行的 ,类似于方面里面的if语句 ,但是预处理不同的是 ,处理完了 ,不满足条件的 ,编译后是不存的 , 而if语句是会怎么的 ,是在运行时做的条件判断
PHP7源码之array_unique函数分析
以下源码基于 PHP 7.3.8
array array_unique ( array array[,intarray[,intsort_flags = SORT_STRING ] ) (PHP 4 >= 4.0.1, PHP 5, PHP 7) array_unique — 移除数组中重复的值 参数说明: array:输入的数组。 sort_flag:(可选)排序类型标记,用于修改排序行为,主要有以下值: SORT_REGULAR - 按照通常方法比较(不修改类型) SORT_NUMERIC - 按照数字形式比较 SORT_STRING - 按照字符串形式比较 SORT_LOCALE_STRING - 根据当前的本地化设置,按照字符串比较。
array_unique 函数的源代码在 /ext/standard/array.c 文件中。由于篇幅过长,完整代码不在这里贴出来了,可以参见 GitHub 贴出的源代码。
定义变量
首先是iosapp完整源码定义变量,array_unique 函数默认使用 PHP_SORT_STRING 排序,PHP_SORT_STRING 在 /ext/standard/php_array.h 头文件中定义。
可以看到和开头PHP函数的sort_flag 参数默认的预定义常量 SORT_STRING 很像。
compare_func_t cmp 这行代码没看懂,不清楚是做什么的。compare_func_t 在 /Zend/zend_types.h 中定义:应该是定义了一个指向int 型返回值且带有两个指针常量参数的函数指针类型,没有查到相关资料,先搁着,继续往下看。
参数解析
ZEND_PARSE_PARAMETERS_START(1, 2),第一个参数表示必传参数个数,第二个参数表示最多参数个数,即该函数参数范围是 1-2 个。
数组元素个数判断
这段代码很容易看懂,当数组为空或只有 1 个元素时,无需去重操作,直接将array 拷贝到新数组 return_value来返回即可。
分配持久化内存
这一步只有当sort_type 为 PHP_SORT_STRING 时才执行。在下面可以看到调用 zend_hash_init 初始化了 array,调用 zend_hash_destroy 释放持久化的内存。
设置比较函数
进行具体比较顺序控制的函数指针是cmp,是通过向 php_get_data_compare_func 传入 sort_type 和 0 得到的,sort_type 也就是 SORT_STRING 这样的标记。
php_get_data_compare_func 在 array.c 文件中定义(即与 array_unique 函数同一文件),gpt源码多大代码过长,这里只贴出默认标记为 SORT_STRING 的代码:
在前面的代码中,我们可以看到,cmp = php_get_data_compare_func(sort_type, 0); 的第二个参数,即参数 reverse 的值为 0,也就是当 sort_type 为 PHP_SORT_STRING 时,调用的是 php_array_data_compare_string 函数,即 SORT_STRING 采用 php_array_data_compare_string 进行比较。继续展开 php_array_data_compare_string 函数:
可以得到这样一条调用链:
string_compare_function 是一个 ZEND API,在 /Zend/zend_operators.c 中定义:
可以看到,SORT_STRING 使用 zend_binary_strcmp 函数进行字符串比较。下面的代码是 zend_binary_strcmp 的实现(也在 /Zend/zend_operators.c 中):
上面的代码是比较两个字符串。也就是SORT_STRING 排序方式的底层实现是 C 语言的 memcmp,即它对两个字符串从前往后,按照逐个字节比较,一旦字节有差异,就终止并比较出大小。
数组排序
这段代码初始化一个新的数组,然后将值拷贝到新数组,然后调用zend_sort 排序函数对数组进行排序。排序算法在 /Zend/zend_sort.c 中实现,注释有这样一句话:
Derived from LLVM's libc++ implementation of std::sort.
这个排序算法是基于LLVM 的 libc++ 中的 std::sort 实现的,算是快排的优化版,当元素数小于等于时有特殊的优化,当元素数小于等于 5 时直接通过 if else 嵌套判断排序。代码就不贴出来了。
数组去重
回到array_unique 上,继续看代码:
遍历排序好的数组,然后删除重复的元素。
众周所知,快排的时间复杂度是O(nlogn),因此,array_unique 函数的时间复杂度是O(nlogn)。array_unique 底层调用了快排算法,加大了函数运行的时间开销,当数据量很大时,会导致整个函数的运行较慢。
通过深挖Clickhouse源码,我精通了数据去重!
数据去重的Clickhouse探索
在大数据面试中,数据去重是一个常考问题。虽然很多博主已经分享过相关知识,但本文将带您深入理解Hive引擎和Clickhouse在去重上的差异,尤其是后者如何通过MergeTree和高效的数据结构优化去重性能。Hive去重
Hive中,distinct可能导致数据倾斜,而group by则通过分布式处理提高效率。面试时,理解MapReduce的数据分区分组是关键。然而,对于大规模数据,Hive的处理速度往往无法满足需求。Clickhouse的登场
面对这个问题,Clickhouse凭借其列存储和MergeTree引擎崭露头角。MergeTree的高效体现在它的数据分区和稀疏索引,以及动态生成和合并分区的能力。Clickhouse:Yandex开源的实时分析数据库,每秒处理亿级数据
MergeTree存储结构:基于列存储,通过合并树实现高效去重
数据分区和稀疏索引
Clickhouse的分区策略和数据组织使得去重更为快速。稀疏索引通过标记大量数据区间,极大地减少了查询范围,提高性能。优化后的去重速度
测试显示,Clickhouse在去重任务上表现出惊人速度,特别是通过Bitmap机制,去重性能进一步提升。源码解析与原则
深入了解Clickhouse的底层原理,如Bitmap机制,对于优化去重至关重要,这体现了对业务实现性能影响的深度理解。总结与启示
对于数据去重,无论面试还是日常工作中,深入探究和实践是提升的关键。不断积累和学习,即使是初入职场者也能在大数据领域找到自己的位置。降低代码的圈复杂度——复杂代码解决之道
本文以Go语言为例,探讨降低代码圈复杂度的重要性与方法。首先,什么是圈复杂度?它是一种用于衡量程序复杂性的软件度量指标,由Thomas J. McCabe, Sr.在年提出。圈复杂度衡量的是程序源代码中的独立路径数量,有助于开发者识别和优化复杂度高的代码。
圈复杂度为何重要?当项目规模增加,业务逻辑复杂,代码可读性差,维护成本随之提高。例如,使用TDD开发时,单测代码量激增,而业务逻辑尚未开始实现。代码过长、嵌套复杂,易导致难以理解、维护困难。为避免此类问题,开发者可在编码、代码审查阶段使用圈复杂度检测工具,通过重构代码结构、减少控制结构(如if、else、while)的使用,将长函数拆分为小而清晰的职责单一函数,或采用设计模式解决复杂逻辑。虽然短期内可能需要重构他人代码,但从长远看,低圈复杂度代码具备更佳的可读性、扩展性和可维护性。
圈复杂度的计算方法主要有节点判定法和工具辅助计算。节点判定法基于公式:圈复杂度 = 节点数量 + 1,其中节点包括条件判断、循环、异常处理等控制结构。使用工具如gocognit可以快速计算代码圈复杂度,辅助代码优化。
如何降低圈复杂度?核心在于减少代码中的控制结构数量。拆分小函数,将复杂业务逻辑分解为单一职责的函数,提高代码可读性和可维护性。优化流程控制语句,避免冗长的if-else嵌套。此外,利用代码重构工具如go-linq简化代码结构,通过流式编程实现代码的简洁与可读性。
go-linq提供了一种简洁的代码风格,支持流式操作,如遍历、筛选、去重、交集、并集等,有助于代码逻辑清晰化。但使用go-linq时应考虑代码的可读性和整体结构,避免盲目追求低圈复杂度而牺牲代码可理解性。
总结而言,降低圈复杂度是提升代码质量、提高可维护性的关键步骤。开发者应根据业务需求和实际场景选择合适的优化策略,利用工具辅助提高代码的可读性和可维护性,从而构建高效、易于维护的软件系统。