【问题标题】:Split string every nth character from the right?从右边开始每隔 n 个字符拆分字符串?
【发布时间】:2017-11-15 03:44:30
【问题描述】:

我有不同的非常大的文件集,我想将它们放在不同的子文件夹中。对于要使用的每个文件夹,我已经有一个连续的 ID。 我想将 ID 从右侧拆分为在更深的级别中始终有 1000 个文件夹。

示例

id:100243 => 结果路径:'./100/243'

id:1234567890 => 结果路径:'1/234/567/890'

我找到了Split string every nth character?,但所有解决方案都是从左到右的,我也不想为一行代码导入另一个模块。

我当前(工作)的解决方案如下所示:

import os

base_path = '/home/made'
n=3    # take every 'n'th from the right
max_id = 12345678900
test_id = 24102442

# current algorithm
str_id = str(test_id).zfill(len(str(max_id)))
ext_path = list(reversed([str_id[max(i-n,0):i] for i in range(len(str_id),0,-n)]))
print(os.path.join(base_path, *ext_path))

输出为:/home/made/00/024/102/442

对于我想做的简单事情,当前的算法看起来既笨拙又复杂。 我想知道是否有更好的解决方案。如果没有,无论如何它可能会帮助其他人。

更新:

我真的很喜欢 Joe Iddons 的解决方案。使用 .join 和 mod 使其更快、更易读。

最后我决定我永远不想在前面有一个/。为了摆脱前面的/以防len(s)%3为零,我将行更改为

'/'.join([s[max(0,i):i+3] for i in range(len(s)%3-3*(len(s)%3 != 0), len(s), 3)])

感谢您的大力帮助!

更新 2:

如果你打算使用os.path.join(就像我之前的代码一样)它会更简单,因为os.path.join负责处理参数本身的格式:

ext_path = [s[0:len(s)%3]] + [s[i:i+3] for i in range(len(s)%3, len(s), 3)]
print(os.path.join('/home', *ext_path))

【问题讨论】:

  • 是否可以将“最大 ID 长度”四舍五入到最接近的 n 倍数?也就是first路径段总长n个字符可以吗?
  • 这是一个起点...从您提供的链接修改答案到此[line[i-n:i] for i in range(len(line), 0, -n)] 得到您['890', '567', '234', '']
  • @DanielPryden:这不是问题。

标签: python string list-comprehension


【解决方案1】:

您可以调整您链接的答案,并利用mod 的美感创建一个漂亮的小one-liner

>>> s = '1234567890'
>>> '/'.join([s[0:len(s)%3]] + [s[i:i+3] for i in range(len(s)%3, len(s), 3)])
'1/234/567/890'

如果您希望它自动添加 dot 以用于您的第一个示例:

s = '100243'

那么您可以添加一个迷你三元组,按照@MosesKoledoye 的建议使用or

>>> '/'.join(([s[0:len(s)%3] or '.']) + [s[i:i+3] for i in range(len(s)%3, len(s), 3)])
'./100/243'

这种方法也会比之前的reversingstringreversinglist更快。

【讨论】:

  • 代替三元,你可以这样做:[s[0:len(s)%3] or '.']
  • @MosesKoledoye 这真的很好,绝对!
【解决方案2】:

如果你有一个从左到右方向的解决方案,为什么不简单地反转输入和输出呢?

str = '1234567890'
str[::-1]

输出:

'0987654321'

您可以使用从左到右找到的解决方案,然后只需再次反转即可。

【讨论】:

  • 谢谢!我认为这正是 Serg Anuke 在上面的回答中所做的。
【解决方案3】:

您可以使用正则表达式和模将字符串分成三个一组。该解决方案应该可以帮助您入门:

import re
s = [100243, 1234567890]
final_s = ['./'+'/'.join(re.findall('.{2}.', str(i))) if len(str(i))%3 == 0 else str(i)[:len(str(i))%3]+'/'+'/'.join(re.findall('.{2}.', str(i)[len(str(i))%3:])) for i in s]

输出:

['./100/243', '1/234/567/890']

【讨论】:

  • 此解决方案应该可以帮助您入门。我不信。相当难以辨认。
【解决方案4】:

试试这个:

>>> line = '1234567890'
>>> n = 3
>>> rev_line = line[::-1]
>>> out = [rev_line[i:i+n][::-1] for i in range(0, len(line), n)]
>>> ['890', '567', '234', '1']
>>> "/".join(reversed(out))
>>> '1/234/567/890'

【讨论】:

    猜你喜欢
    • 2020-08-13
    • 1970-01-01
    • 2012-03-17
    • 1970-01-01
    • 2018-10-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多