在给定格式为{a.b.c.d
等的域中,strings
之间的'.' is > 1
数是什么?他的后缀列表,按最长的后缀排序,降序排列。
例如,给定www.hello.com
,我想要以下输出:
['www.hello.com', 'hello.com', 'com']
答案 0 :(得分:3)
这应该有效:
s = 'www.hello.com'
splits = s.split('.')
['.'.join(splits[i:]) for i in range(len(splits))]
# ['www.hello.com', 'hello.com', 'com']
我不确定这是否是最佳选择,但第一件事出现在我的脑海中。
答案 1 :(得分:2)
如果您使用split
参数'.'
上的字符串,则最后一个元素将是后缀:
maxsplit
因此,您只需要获取每个拆分的最后一个元素:
>>> domain = 'www.hello.com'
>>> domain.split('.', 0)
['www.hello.com']
>>> domain.split('.', 1)
['www', 'hello.com']
>>> domain.split('.', 2)
['www', 'hello', 'com']
这是“ 非常理想”吗?我不知道。相当快:
>>> [domain.split('.', i)[-1] for i in range(domain.count('.')+1)]
['www.hello.com', 'hello.com', 'com']
与Arman's solution相比,由于In [259]: %timeit [domain.split('.', i)[-1] for i in range(domain.count('.')+1
2.43 µs ± 121 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
的成本,我希望会有一个小的常数因数差异,但我们不做猜测,而是进行测试:
join
所以,是的,它慢了约55%(实际上比我预期的还快),但在这里,我们所说的是微秒。
我们可以更快地提出一些建议吗?也许吧,但是会更加冗长。我们正在整个字符串上反复调用In [261]: s = domain
In [262]: %timeit ['.'.join(s.split('.')[i:]) for i in range(len(s.split('.')))]
3.79 µs ± 119 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
。如果我们仅split
一次并split
次多次该怎么办?我怀疑join
会更快一点,因为它不涉及搜索,直到您找到足够大的字符串(分配速度更快)为止,但是同样,让我们不要猜测,让我们测试一下:
join
嗯,节省了20纳秒。
从技术上讲,这两种解决方案都具有二次复杂性。
我们可以在线性时间内做到吗?
首先,如果我们只得到In [264]: %timeit parts=domain.split('.'); ['.'.join(parts[i:]) for i in range(len(pats))]
2.41 µs ± 86.6 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
的位置并进行切片怎么办?那实际上仍然是二次时间,因为每个切片仍然是线性时间操作,即使它比.
或split
快得多。
但是我们在Python中所做的 在这里肯定是二次的。我们必须创建N个新字符串,其平均长度是N的倍,这意味着将分配和复制join
个字符。
如果我们可以得到一个新的字符串对象,该对象引用与N*N
相同的字符串缓冲区…那么,您不能在Python中做到这一点,但是理论上可以在C语言中做到这一点。但是首先,让我们看看是否看起来值得做:
domain[pos:]
这是比较麻烦的时间,但是需要7.02µs。所有这些额外的工作以及所有这些额外的pos = 0
dots = []
while True:
dots.append(pos)
pos = domain.find('.', pos)
if pos == -1: break
pos += 1
[domain[pos:] for pos in dots]
浪费的时间比我们节省的时间要多得多。也许如果您有大量的组件,那值得,但是只需三个?我对此表示怀疑。
即使不共享字符串缓冲区,用C编写此逻辑也可能比使用if
或split
更快,然后诱使Python在该共享缓冲区周围构造字符串对象可能节省更多时间…但是,除非这2微秒确实是代码中的瓶颈,否则您真的要在这里编写C扩展吗? (而且,您必须非常小心地使用它们-字符串对象希望拥有其存储空间,并且您不希望拆分删除它们不拥有的缓冲区…)
如果您确实需要提高速度,因为您的字符串是纯ASCII,则可以使用join
来节省更多时间。 (然后您甚至可以bytes
使用它来避免复制切片,但是这样做的代价是无法memoryview
做它们,而无需执行额外的步骤……)当然,字节的使用不太方便,如果您可以使用人类可读的Unicode代替IDNA punycode,就可以使用IDNA域,那么它将根本无法工作...