字符串 - 删除和拼接
我始终是觉得, 在处理字符串这块, 两个重要点是, split 分割, 和 正则表达式这两个大头, 其余的还好吧. split 是为了处理结构化, 规则明确的 "分割", 正则则是万能的, 尤其是 re.match, re.findall, re.sub ... 是经常会用到的. 然后呢, 这里继续来一些修修补补的内容哇, 主要也是再留个印象, 和为自己以后用到时会首先搜索一波自己的笔记.
果然, 搞来搞去, 还是最基本概念, 基本功最为重要的. 而并非什么新算法, 框架, 项目啥的, 都搞腻了...
删除不需要的字符
需求
需删除字符串的开头, 结尾或中间不想要的字符, 比如空白.
方案
用 字符串的 strip() 实现, 衍生的 lstrip() 和 rstrip() 分别从左, 右, 执行删除特定字符 (默认删除 "空格")
s = ' hello world \n'
# strip 默认删除空白, 并返回新对象哦
print('raw:', s)
print('both:', s.strip())
print('left:', s.lstrip())
print('right:', s.rstrip())
# 删除特殊字符
t = '------youge========'
print('raw:', t)
print('left:', t.lstrip('-'))
print('right', t.rstrip('='))
print('both', t.strip('-='))
raw: hello world
both: hello world
left: hello world
right: hello world
raw: ------youge========
left: youge========
right ------youge
both youge
大多数情况下, 直接用 strip() 就基本能搞定了. 但有个 bug 是, 对于字符串中中间的文本空格, 并不产生影响.
s = 'hello world youge !\n'
print(s.strip())
hello world youge !
这就非常的鸡肋了. 中间的 空格, 我自己还得用 replace () 来处理, 要这 strip() 有何用 ...
'# 来一波, 链式调用...
s.strip().replace(' ', '')
'helloworldyouge!'
我最近的一个场景是, 用正则匹配特殊字符, 并进行替换.
re.complie(u"[\U00010000-\U0010ffff]")
用的比较多就是文件处理, 像数据类的如 Excel, csv 这些,我会用到 DataFrame 来处理, 其实很笨, 遍历每个单元格来查找特殊字符并替换. 其次是一般的文件处理, 结合生成器来弄.
# 结合生成器
with open(file_name) as f:
lines = (line.strip() for line in f)
# 生成器两种方式: 元组推导时 或者 函数中使用 yield 代替 return
# 生成器,运行时不占内存, 真正用时才会 "懒加载"
for line in lines:
print(line)
字符串对齐
需求
对字符串进行 左对齐, 右对齐, 居中对齐等...
方案
用 ljust(), rjust(), center() 来实现即可. 当然, 我感觉真实中的用处并不大, 我是基本没有用到过.
text = "hello, world!"
print("左对齐:", text.ljust(20))
print("右对齐:", text.rjust(20))
print("居中对齐:", text.center(len(text)))
print("补全:", text.ljust(50, "*"))
左对齐: hello, world!
右对齐: hello, world!
居中对齐: hello, world!
补全: hello, world!*************************************
然后还有格式化的常用 3个方法: %s, format(), f"({variable})". 就不展开了. %s 这种占位符方式, 我在拼接 sql 的时候, 就执拼接 executemany( 'insert into tb_name ..', args=xxx) 会用到. 自用我用了 f"{变量}" 的写法后, 就再也没有用过 format() 方法了, 觉得不够简洁和优雅呢.
字符串拼接
需求
跟 split() 逆向操作, 即要把几个小的字符串合并为一个大的字符串
方案
用 join( ) 函数可实现 一些 序列或者 iterable 中, 更加简单的用 "+" 即可.
words = ['nice', 'to', 'see', 'you']
# 用空格来拼接为一个字符串
print(' '.join(words))
# 用自定义符号来拼接
print("* ".join(words))
nice to see you
nice* to* see* you
更加简单的字符串拼接, 用 "+", 注意, 正好最近在看 js 代码嘛, 需要说明一下, 正好做一个对比学习.
- Pyhton 是一门 动态(无需声明变量类型), 强类型 语言 (比如 字符串 是不能 和 数字 "拼接" 运算的)
- JavaScript 是一门, 动态, 弱类型 语言 (在 js 中, 数字和字符串是可以运算的, 就很不严谨, 我感觉
a = 'how'
b = 'are'
c = 'you'
print(a + ' ' + b + ' ' + c)
how are you
我怎么, 感觉现在我经常来看这些基础的问候语句的时候, 觉得境界不一样了, 像, "hello, world", 人生若只如初见, "how are you ", 你还好吗 ... 这类的话语格外温暖和亲切.
字符串拼接,这样一个看似极为基础的事情, 讨论的意义, 更多是有性能方面考量的. 需注意的是, 当我们使用 "+" 操作符去大量连接字符串的时候, 效率是非常低的. 因为 "+" 会引起内存复制和垃圾回收.
# 反例: 希望我以后再也不要这样写
s = ''
for i in words:
s += i
不推荐用 "+" : 每次执行 "+= " 的时候, 都会创建一个新的字符串对象
那推荐的, 自然是使用生成器表达式来进行合并了呀, 结合 join 来处理, 这才简洁优雅哦, 简洁不是简单呢.
lst = ['My', 'score', 'is', 99.66]
print(
','.join(str(i) for i in lst)
)
My,score,is,99.66
查了下, 也不是绝对哈. 当混合使用 I/O 操作的时候, 需要具体来研究一下程序.
# v1:
f.write(s1 + s2)
# v2:
f.write(s1)
f.write(s2)
如果两个字符串非常小, v1 版本反而会更好些, 因为 I/O 操作本就是一个耗时操作哦; 但当非常大的时候, v2 的优势就体现出来了, 因为它避免了, "+" 会不断创建临时结果且需要复制大量的内存数据块.
如果是要写一个大量小字符串的输出代码, 可以考虑使用生成器, 用 yield 来输出片段.
def sample():
yield 'how'
yield 'are'
yield 'you'
yield 'youge'
# list(sample())
# 可以用 join() 将这些片段合并起来
' '.join(sample())
# 或者重定向到文件
for i in sample:
f.write(i, '\n')
# 来一个混合方案, 结合 I/O 操作
def combine(source, maxsize):
lst = []
size = 0
for part in source:
lst.append(part)
size += len(part)
# maxsize 作为一个阈值
if size > maxsize:
yield ' '.join(lst)
# 然后再重新计数, 进入下一轮
lst = []
size = 0
yield ' '.join(lst)
# 结合文件操作
with open('youge.txt', 'w') as f:
for part in combine(sample(), 12345):
f.write(part)
这样一来, 用上生成器后, 整个代码的美感就上来的, 简洁, 优雅, 高性能, 是我喜欢的.