properties数据处理
1、介绍
1.1 数据结构
properties数据指的是一组或多组键值对数据结构,list[list[str, str]]。
二维数组结构,其中一维的元素是长度为2的list,二维的元素是str类型,分别表示键和值。
1.2 场景
在诸多业务场景中,存在使用properties数据的需求。
- 配置文件
- 请求和响应头部
- url的直接参数
- 请求体部
- cookies
1.3 函数和类
为了方便处理properties数据,定义相关的函数和类。之所以不直接使用list或dict进行处理,大概以下几点:
- dict要求键是不可重复的,会自动去重。但是类似响应头部set-cookie字段是需要允许键重复的
- list的copy是浅复制,但需求一般是深复制。所以需要定义函数和方法
- dict和list都不强调元素是str类型,而properties函数和类都强调键和值都为str类型
- 编写函数和类,能够显著的节俭代码,进行复用
2、PropertiesModule
定义了相关的函数
2.1 parse
parse(s, sep1, sep2, strip_flag=False)->list[list[str, str]]
- 解析字符串为properties数据结构,即二维list,其中一维的元素是长度为2、元素为str的list
- s,str类型,待解析字符串
- sep1,str类型,键值对和键值对之间的分隔符
- sep2,str类型,键和值之间的分隔符
- strip_flag,bool类型,为True表示会对键和值进行去除首尾空白字符,即调用.strip()方法
- 如果s、sep1、sep2任一者为空字符串,则直接返回空list []
2.2 toString
toString(arr, sep1, sep2)->str
- 将properties数据结构,组装为str类型返回。如果arr长度为0,返回空字符串''
- arr,为properties数据结构,即二维list,其中一维的元素是长度为2、元素为str的list
- sep1,str类型,键值对和键值对之间的分隔符
- sep2,str类型,键和值之间的分隔符
2.3 clone
clone(arr) -> list[list[str, str]]
- 深克隆,即克隆二维的str字面值。而非浅克隆只克隆一维的地址
- arr,为properties数据结构,即二维list,其中一维的元素是长度为2、元素为str的list
2.4 hasName
hasName(arr, name, ignore_case) -> bool
- 判断properties数据结构中是否包含某键,包含则返回bool类型的True
- arr,为properties数据结构,即二维list,其中一维的元素是长度为2、元素为str的list
- name,str类型,待匹配键名称
- ignore_case,bool类型,是否忽略大小写进行匹配。如果为True,会将各键转小写,以及name转小写进行匹配
2.5 getFirstValue
getFirstValue(arr, name, ignore_case, default=None) -> str/None
- 获取首个键匹配所对应的值,如果没有匹配,则返回default
- arr,为properties数据结构,即二维list,其中一维的元素是长度为2、元素为str的list
- name,str类型,待匹配键名称
- ignore_case,bool类型,是否忽略大小写进行匹配。如果为True,会将各键转小写,以及name转小写进行匹配
- default,默认值为None,即没有任何匹配时所返回。使用时可以考虑根据需求设置为空字符串''或其它字符串
2.6 getValue
getValue(arr, name, ignore_case) -> list[str]
- 获取键所匹配的所有值,返回类型list[str]。主要是针对响应头部set-cookie这类允许重复的键
- arr,为properties数据结构,即二维list,其中一维的元素是长度为2、元素为str的list
- name,str类型,待匹配键名称
- ignore_case,bool类型,是否忽略大小写进行匹配。如果为True,会将各键转小写,以及name转小写进行匹配
2.7 remove
remove(arr, name, ignore_case)
- 移除所有键所匹配的项
- arr,为properties数据结构,即二维list,其中一维的元素是长度为2、元素为str的list
- name,str类型,待匹配键名称
- ignore_case,bool类型,是否忽略大小写进行匹配。如果为True,会将各键转小写,以及name转小写进行匹配
- 需要注意,这里移除的算法需要考虑移除某项后对其它项的索引影响
- 思路一,是使用while,索引递增判断,如果执行移除,则不+1再次判断。反之不移除则+1
- 思路二,准备新的存储对象,索引递增判断,如果需要移除则不添加到新存储对象,反之则添加
2.8 update
update(arr: list, name: str, value: str, ignore_case: bool):
- 更新所有键所匹配的项
- arr,为properties数据结构,即二维list,其中一维的元素是长度为2、元素为str的list
- name,str类型,待匹配键名称
- value,str类型,更新的值
- ignore_case,bool类型,是否忽略大小写进行匹配。如果为True,会将各键转小写,以及name转小写进行匹配
2.9 add
add(arr: list, name: str, value: str):
- 添加一组键值对
- arr,为properties数据结构,即二维list,其中一维的元素是长度为2、元素为str的list
- name,str类型,键名称
- value,str类型,值
2.10 getNames
getNames(arr) -> list[str]
- 获取所有的键,返回类型list[str]
- arr,为properties数据结构,即二维list,其中一维的元素是长度为2、元素为str的list
3、代码
PropertiesModule.py
"""
解析函数,将字符串s解析为properties结构,比如'a=1&b=2'解析为[['a','1'],['b','2']]
@s 待解析文本
@sep1 属性值对与属性值对之间的间隔
@sep2 属性值对内部,名称和值的间隔
@strip_flag 是否对解析后的名称和值,去除前后的空白符
"""
def parse(s: str, sep1: str, sep2: str, strip_flag: bool = False):
"""parse(s, sep1, sep2, strip_flag=False)->list[list[str, str]]"""
# 返回对象
result = []
# 如果存在空字符串,直接结束
if s == '' or sep1 == '' or sep2 == '':
return result
items = s.split(sep1)
for i in range(len(items)):
if sep2 in items[i]:
split = items[i].split(sep2, maxsplit=1)
if strip_flag:
split[0], split[1] = split[0].strip(), split[1].strip()
result.append([split[0], split[1]])
return result
"""
拼接字符串 比如[['a','1'],['b','2']]拼接为'a=1&b=2'
@arr: 属性值对列表
@sep1 属性值对与属性值对之间的间隔
@sep2 属性值对内部,名称和值的间隔
"""
def toString(arr: list, sep1: str, sep2: str):
"""toString(arr, sep1, sep2)->str"""
result = ''
if len(arr) > 0:
result = arr[0][0] + sep2 + arr[0][1]
for i in range(1, len(arr)):
result = result + sep1 + arr[i][0] + sep2 + arr[i][1]
return result
"""
克隆属性值对,深层克隆,克隆值
@arr: 属性值对列表
"""
def clone(arr: list):
"""clone(arr) -> list[list[str, str]]"""
# list的copy是浅克隆,但是这里list的元素都是list,所以不能直接用
result = []
for i in range(len(arr)):
result.append([arr[i][0], arr[i][1]])
return result
"""
匹配属性值对的名称,如果存在匹配则返回True,否则返回False
@arr: 属性值对列表
@name: 属性名称
@ignoreCase 忽视大小写匹配
"""
def hasName(arr: list, name: str, ignore_case: bool):
"""hasName(arr, name, ignore_case) -> bool"""
for item in arr:
if item[0] == name or (ignore_case and item[0].lower() == name.lower()):
return True
return False
"""
匹配属性值对的名称,返回第一次匹配项的值
@arr: 属性值对列表
@name: 属性名称
@ignoreCase 忽视大小写
@return 如果匹配则返回值,没有匹配项则返回default,默认是None
"""
def getFirstValue(arr: list, name: str, ignore_case: bool, default=None):
"""getFirstValue(arr, name, ignore_case, default=None) -> str/None"""
for item in arr:
if item[0] == name or (ignore_case and item[0].lower() == name.lower()):
return item[1]
return default
"""
匹配属性值对的名称,返回所有匹配项的值
@arr: 属性值对列表
@name: 属性名称
@ignoreCase 忽视大小写
"""
def getValue(arr: list, name: str, ignore_case: bool):
"""getValue(arr, name, ignore_case) -> list[str]"""
result = list()
for item in arr:
if item[0] == name or (ignore_case and item[0].lower() == name.lower()):
result.append(item[1])
return result
"""
移除
@arr: 属性值对列表
@name: 属性名称
@ignoreCase 忽视大小写
@return 直接在arr对象上操作,无返回
"""
def remove(arr: list, name: str, ignore_case: bool):
"""remove(arr, name, ignore_case)"""
i = 0
while i < len(arr):
if arr[i][0] == name or (ignore_case and arr[i][0].lower() == name.lower()):
del arr[i]
# continue很重要,匹配移除当前索引的元素,然后再判断当前索引
continue
i = i + 1
"""
更新
@arr: 属性值对列表
@name: 属性名称
@value: 属性值
@ignoreCase 忽视大小写
@return 直接在arr对象上操作,无返回
"""
def update(arr: list, name: str, value: str, ignore_case: bool):
for item in arr:
if item[0] == name or (ignore_case and item[0].lower() == name.lower()):
item[1] = value
"""
追加
@arr: 属性值对列表
@name: 属性名称
@value: 属性值
@return 直接在arr对象上操作,无返回
"""
def add(arr: list, name: str, value: str):
arr.append([name, value])
"""
返回名称列表
@arr: 属性值对列表
@return list类型
"""
def getNames(arr: list):
"""getNames(arr) -> list[str]"""
result = []
for i in range(len(arr)):
result.append(arr[i][0])
return result
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· 没有源码,如何修改代码逻辑?
· PowerShell开发游戏 · 打蜜蜂
· 在鹅厂做java开发是什么体验
· WPF到Web的无缝过渡:英雄联盟客户端的OpenSilver迁移实战