使用Polars DataFrame查找列表中出现次数为奇数的整数
简洁的Polars实现方案
针对你需要找出每个子列表中出现次数为奇数的整数的需求,这里提供两种更简洁高效的Polars实现方式:
方法一:利用异或特性(最优性能)
因为一个整数出现偶数次时,异或运算会抵消为0,奇数次则保留自身,结合题目示例中每个子列表仅存在一个目标数的特点,这个方法性能最优:
import polars as pl from time import perf_counter with open("samples.json", "r") as file: data = file.read() t_start = perf_counter() result = ( pl.LazyFrame({"data": data}) .select(pl.col("data").str.json_decode()) .explode("data") .with_columns( target = pl.col("data").list.eval(pl.element().reduce(lambda a, b: a ^ b)) ) .collect() .get_column("target") .to_list() ) t_stop = perf_counter() print(result) print(f"Compute {round((t_stop-t_start) * 1000, 2)}ms")
方法二:基于value_counts的通用简化版
如果需要兼容子列表可能存在多个奇数次出现的数的场景,可以简化原有的value_counts流程:
import polars as pl from time import perf_counter with open("samples.json", "r") as file: data = file.read() t_start = perf_counter() result = ( pl.LazyFrame({"data": data}) .select(pl.col("data").str.json_decode()) .explode("data") .with_columns( target = pl.col("data").list.eval( pl.element().value_counts().filter(pl.col("count") % 2 == 1).select("value") ) ) .collect() .get_column("target") .to_list() ) t_stop = perf_counter() print(result) print(f"Compute {round((t_stop-t_start) * 1000, 2)}ms")
优化说明
- 原方案多次使用
explode和group_by,步骤繁琐且存在不必要的性能损耗;优化后的方案直接在列表列上通过list.eval完成计算,避免了数据反复展开与分组的冗余操作。 - 方法一依赖异或的数学特性,时间复杂度为O(n),是特定场景下的性能最优解;方法二更通用,能处理子列表中有多个目标数的情况。
内容的提问来源于stack exchange,提问作者bwebb
相关产品推荐
相关产品推荐

