如何检查字符串子串是否在字典键中及PySpark相关技术咨询
嘿,我给你拆解一下这几个问题哈!
一、处理部分字符串匹配与忽略大小写
不管是遇到"Mexican Pepper"这种包含关键词的项,还是"Tomato"和"tomato"这种大小写差异的情况,核心思路是统一文本格式+子串/正则匹配。
1. 基础实现:统一大小写+子串匹配
先把字典里的关键词和输入项都转成小写,消除大小写差异;然后检查输入项的小写形式是否包含某个类别下的关键词(同样转小写)。
假设你的类别字典是这样的(可以替换成你自己的):
category_dict = { "fruit": ["apple", "banana"], "vegetable": ["pepper"], "junk food": ["pizza"] } grocery_list = ["apple","bananas","pizza","pepper", "Mexican Pepper", "tomato"]
对应的处理代码:
# 先把字典里的关键词全部转小写,方便后续统一比对 lowercase_category_map = { cat: [kw.lower() for kw in keywords] for cat, keywords in category_dict.items() } def get_item_category(item): item_lower = item.lower() # 遍历每个类别,检查是否有匹配的关键词 for category, keywords in lowercase_category_map.items(): for keyword in keywords: if keyword in item_lower: return category # 没有匹配到就返回默认类别,比如"unknown" return "unknown" # 测试一下效果 for item in grocery_list: print(f"{item} → {get_item_category(item)}")
运行后会输出:
apple → fruit bananas → fruit pizza → junk food pepper → vegetable Mexican Pepper → vegetable tomato → unknown
2. 进阶优化:正则表达式匹配
如果你的关键词比较复杂(比如带特殊字符、需要更灵活的匹配规则),可以用正则表达式,结合re.IGNORECASE参数直接忽略大小写:
import re # 为每个类别构建正则模式,匹配该类别下的任意关键词 category_regex_map = { cat: re.compile('|'.join(keywords), re.IGNORECASE) for cat, keywords in category_dict.items() } def get_item_category_regex(item): for category, pattern in category_regex_map.items(): if pattern.search(item): return category return "unknown" # 测试效果和基础版一致 for item in grocery_list: print(f"{item} → {get_item_category_regex(item)}")
二、统计各类别出现次数
结合上面的分类函数,用collections.Counter就能轻松统计:
from collections import Counter category_counter = Counter() for item in grocery_list: category = get_item_category(item) category_counter[category] += 1 print("类别统计结果:", category_counter) # 输出:类别统计结果: Counter({'fruit': 2, 'vegetable': 2, 'junk food': 1, 'unknown': 1})
三、关于PySpark的使用
当然可以用PySpark来处理!尤其是当你的购物清单数据量极大(比如百万级甚至更多),PySpark的分布式处理能力能帮你高效完成任务。
这里给你两种实现思路:
1. 用UDF(用户自定义函数)实现
适合逻辑复杂的场景,把类别字典做成广播变量(避免每个节点都复制一份,节省资源):
from pyspark.sql import SparkSession from pyspark.sql.functions import udf from pyspark.sql.types import StringType # 初始化Spark会话 spark = SparkSession.builder.appName("GroceryCategoryAnalysis").getOrCreate() # 把购物清单转成Spark DataFrame grocery_df = spark.createDataFrame( [("apple",), ("bananas",), ("pizza",), ("pepper",), ("Mexican Pepper",), ("tomato",)], ["item"] ) # 广播类别字典 broadcast_category = spark.sparkContext.broadcast(category_dict) # 定义UDF函数 @udf(StringType()) def get_category_spark(item): item_lower = item.lower() for cat, keywords in broadcast_category.value.items(): for kw in keywords: if kw.lower() in item_lower: return cat return "unknown" # 添加类别列并统计 result_df = grocery_df.withColumn("category", get_category_spark(grocery_df["item"])) result_df.groupBy("category").count().show()
执行后会输出:
+-----------+-----+ | category|count| +-----------+-----+ | fruit| 2| |junk food | 1| | vegetable| 2| | unknown| 1| +-----------+-----+
2. 用Spark内置函数实现(性能更优)
如果逻辑简单,尽量用Spark内置函数,避免UDF的性能开销:
from pyspark.sql.functions import lower, regexp_extract, when # 构建正则模式,分组对应不同类别 pattern = r"(apple|banana)|(pepper)|(pizza)" result_df = grocery_df.withColumn( "category", when(regexp_extract(lower(grocery_df["item"]), pattern, 1) != "", "fruit") .when(regexp_extract(lower(grocery_df["item"]), pattern, 2) != "", "vegetable") .when(regexp_extract(lower(grocery_df["item"]), pattern, 3) != "", "junk food") .otherwise("unknown") ) result_df.groupBy("category").count().show()
这个方法和UDF的结果一致,但在大数据量下速度更快。
内容的提问来源于stack exchange,提问作者A.Dorra
相关产品推荐
相关产品推荐

