字符串 - 删除和拼接

我始终是觉得, 在处理字符串这块, 两个重要点是, 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) 

这样一来, 用上生成器后, 整个代码的美感就上来的, 简洁, 优雅, 高性能, 是我喜欢的.

posted @ 2020-06-07 23:57  致于数据科学家的小陈  阅读(527)  评论(0编辑  收藏  举报