2. 复杂场景下字符串处理相关问题与解决方法

一. 如何判断字符串a是否以字符串b开头或结尾?

实际案列

某文件系统目录下有一系列文件:
quicksort.c
graph.py
heap.java
install.sh
stack.cpp

编写程序给其中所有.sh文件 和 .py文件加上用户可执行权限

解决方案

使用str.startswith() 和 str.endswith() 方法
(注意: 多个匹配时参数使用元组)

要用到的python代码技术点

s = os.stat('b.py')    # 获取文件状态的 对象

# ls -l b.py
# -rw-r--r-- 1 cannon  cannon 0 Mar  12 14:06 b.py

oct(s.st_mode)   # 0o100644   权限的八进制  644

s.st_mode | 0o100   # 0o100744

os.chmod('b.py', s.st_mode | 0o100)   # 修改b.py可执行权限

代码实现

import stat, os

for fn in os.listdir():
    if fn.endswith('.py', '.sh'):
        fs = os.stat(fn)
        os.chmod(fn, fs.st_mode | stat.S_IXUSR)



二. 如何调整字符串中文本的格式

实际案例

某软件的log文件, 其中的日期格式为'yyyy-mm-dd':

2016-05-21 10:39:26 statys unpacked python3-pip:all
2016-05-23 10:49:26 status half-configured python3
....



我们想要把其中日期改为美国日期的格式  'mm/dd/yyyy'
即  '2016-05-23' => '05/23/2016', 应该如何处理?

解决方案

使用正则表达式re.sub() 方法 做字符串替换, 利用正则表达式的组, 捕获每个部分内容, 在替换字符串中调整各个捕获组的顺序
log = "2016-05-21 10:39:26 statys unpacked python3-pip:all
2016-05-23 10:49:26 status half-configured python3"




import re

re.sub('(\d{4})-(\d{2})-(\d{2})', r'\2/\3/\1', log)


# 或者可以给组命名
re.sub('(?P<d>\d{4})-(?P<m>\d{2})-(?P<y>\d{2})', r'\g<m>/\g<d>/\g<y>', log)

三. 如何将多个小字符串拼接成一个大的字符串

实际案例

在设计某网络程序时, 我们自定义了一个基于UDP的网络协议
按照固定次序想服务器传递一系列参数:
hwDetect: "<0112>"
gxDepthBits: "<32>"
gxResolution: "<1024x768>"
gxRefresh: "<60>"
fullAlpha: "<1>"
lodDist: "<100.0>"
DistCull: "<500.0>"

在程序中我们将各个参数按次序手机到列表中:
["<0112>", "<32>", "<1024x768>", "<60>", "<1>", "<100.0>", "<500.0>"]
最终我们要把各个参数拼接成一个数据报进行发送
"<0112><32><1024x768><60><1><100.0><500.0>"

解决方案

使用str.join()方法, 快速拼接列表中所有字符串

l = ["<0112>", "<32>", "<1024x768>", "<60>", "<1>", "<100.0>", "<500.0>"]
''.join(l)

四. 如何对字符串进行左右 居中对齐

实际案列

某个字典存储了一系列属性值
{
    "lodDist": 100.0,
    "SmallCull": 0.04,
    "DistCull": 500.0,
    "trilinear": 40, 
    "farclip":477
}

在程序中, 我们想以工整的格式将其内容输出, 如何处理?
SmallCull: 0.04
farclip  : 477
lodDist  : 100.0
DistCull : 500.0
trilinear: 40

解决方案

方法一: 使用字符串的str.ljust(), str.rjust(), str.center() 进行左 右 居中对齐

s = 'abc'
s.ljust(10)
# 'abc       '

# 如果传入 2  比s的长度都小  不会做任何处理
s.ljust(2)
# 'abc'

# 指定填充的字符, 只能指定一种字符
s.ljust(*10)
# 'abc*******'




方法二: 使用format()方法, 触底类似'<20','>20', '^20'参数完成同样任务


# 左对齐
format(s, '<10')
# 'abc       '

# 右对齐
format(s, '>10')
# '       abc'

# 居中对齐
format(s, '^10')
# '   abc    '

# 空余用*填充
format(s, '*^10')
# '***abc****'

# 对于数字的用法
# + 表示无论征正负 总输出符号
format(10, '+')
# '+10'

format(-10, '+')
# '-10'


# = 表示符号在左  数字在右  
format(567, '0=+10')
# '+000000567'

解题代码


d = {
    "lodDist": 100.0,
    "SmallCull": 0.04,
    "DistCull": 500.0,
    "trilinear": 40,
    "farclip": 477
}

w = max(map(len, d.keys()))   # key中最长的 作为对齐的宽度
for k, v in d.items():
    print(k.ljust(w), ':', v)

五. 如何去掉字符串中不需要的字符

实际案列

1. 过滤掉用户输入中前后多余的空白字符:
    ' [email protected] '

2. 过滤某windows 下编辑文本中的'\r':
    'hello world\r\n'
    
3. 去掉文本中的unicode组合符号(音调):
    'ní hǎo, chīfàn'

解决方法

方法一.  字符串strip(), lstrip(), rstrip() 方法去掉字符串两端字符

s = '\t =+-*[email protected]==== \t'  # 空白字符  包含\t
s.strip() # 两端空白字符都去掉
s.lstrip() # 去掉左边的空白字符
s.rstrip() # 去掉右边的空白字符

s.strip('=+-*') # 两端+-=*都去掉



方法二. 删除单个固定位置的字符, 可以使用切片 + 拼接的方式

s2 = 'abc:1234'
s2[:3] + s2[4:]


方法三. 字符串的replace()方法或正则表达式re.sub()删除任意子串

s3 = '   abc   xyz   '   # strip 无法去掉中间的空格
s3.replace(' ', '')

s3 = '\t   abc  \t  xyz  \n'  # replace就比较麻烦了

import re
re.sub('[ \t\n]+', '', s3)
re.sub('\s+', '', s3)  # \s 表示空白符号


方法四. 字符串的translate()方法, 可以同时删除多种不同字符

s = 'abc1234xyz'
# 如何把a变为X  b变为Y
s.translate({ord('a'): 'X', ord('b'): 'Y'})  # 映射表的key必须是unicode值    value可以是unicode值也可以是字符

# 也可以利用makestrans获取unicode映射表
s.maketrans('ab', 'XY')  # 要一一对应
# {97:88, 98:89}

s.translate(s.maketrans('ab', 'XY'))

# 删除s中的a
s.translate({ord('a'): None})



# 去除拼音的音调
s4 = 'ní hǎo, chīfàn'

print(s4.translate(s4.maketrans('íǎīà', 'iaia')))

# 'ni hao, chifan'

六. 分割字符串问题

实际案例

已知字符串"ab;cd|efg|hi,jk1|mn\topq;rst,uvw\txyz", 
其中的',' ';' '|' '\t' 都是分割符,如何处理?

方法1、 连续使用str.split


s = "ab;cd|efg|hi,jk1|mn\topq;rst,uvw\txyz"

def my_split(s, seps):
  res = [s]
  for sep in seps: 
    t = []
    map(lambda ss: t.extend(ss.split(sep)), res)
    res = t
  return res

print(my_split(s, ',;|\t'))

结果

['ab', 'cd', 'efg', 'hi', 'jk1', 'mn', 'opq', 'rst', 'uvw', 'xyz']

或者通过reduce

from functools import reduce

my_split2 = lambda s, seps: reduce(lambda l, sep: sum(map(lambda ss: ss.split(sep), l), []), seps, [s])
print(my_split2(s, ',;|\t'))

结果

['ab', 'cd', 'efg', 'hi', 'jk1', 'mn', 'opq', 'rst', 'uvw', 'xyz']

此方法因为不方便阅读,所以不推荐


方法2、 正则表达式re.split方法(推荐)

import re
print(re.split('[;,|\t]+', s))

结果

['ab', 'cd', 'efg', 'hi', 'jk1', 'mn', 'opq', 'rst', 'uvw', 'xyz']

猜你喜欢

转载自blog.csdn.net/weixin_41207499/article/details/83004215
今日推荐