逐元素字符串比较

Posted

技术标签:

【中文标题】逐元素字符串比较【英文标题】:Element-wise string comparison 【发布时间】:2012-12-19 10:27:14 【问题描述】:

我需要一个快速函数来对两个字符串进行逐元素比较。示例:

text1 = 'absabeadg'
text2 = 'abSatyaxguz'
diff = compare(text1,text2) # should return diff=[1,1,0,1,0,0,1,0,1,0,0]

【问题讨论】:

欢迎来到 SO。你都尝试了些什么?这不是代码编写服务。 出于好奇:为什么需要快速?即使是我能想到的最慢的方法,仍然会如此快速地处理这种大小的字符串,以至于你永远不会注意到时间。 【参考方案1】:

显示了零努力,但到底是什么,现在是周末:

>>> text1 = 'absabeadg'
>>> text2 = 'abSatyaxguz'
>>> 
>>> from itertools import izip_longest
>>> 
>>> [int(c0==c1) for c0, c1 in izip_longest(text1, text2)]
[1, 1, 0, 1, 0, 0, 1, 0, 1, 0, 0]

这使用izip_longest 将(可能)不同长度的序列组合在一起,以及int(True) == 1int(False) == 0 的事实。

[更新:]

由于关于这个输出是否有意义似乎存在一些争议,这里有一个不同的方法给出相同的答案:

>>> [int(text1[i:i+1] == text2[i:i+1]) for i in range(max(len(text1), len(text2)))]
[1, 1, 0, 1, 0, 0, 1, 0, 1, 0, 0]

(据我所知,辩论似乎是关于在将任何内容与某物进行比较时返回 0 是否有意义。我认为这是完全合理的,并且是字符串切片的行为方式——我们可以比较将空字符串转换为非空字符串并始终得到False == 0。)

【讨论】:

【参考方案2】:

对于 no-import-modules-readable-solution 我猜你可以只使用这个:)

text1 = "absabeadg"
text2 = "abSatyaxguz"
len1 = len(text1)
len2 = len(text2)
result = []
for index in range(min(len1, len2)):
    result.append(int(text1[index] == text2[index]))
result.extend([0]*abs(len1-len2))
print result

对于列表理解的乐趣:

text2 = "absabeadg"
text1 = "abSatyaxguz"
len1 = len(text1)
len2 = len(text2)

print [int(text1[i] == text2[i]) for i in range(min(len1, len2))] + [0]*abs(len1-len2)

【讨论】:

如果text1text2 长,这不会给出正确答案。也许[0 if len1 < len2 else 1]*abs(len1-len2)?另外,我打赌列表理解将比手动 append 循环更快,并且 OP 确实明确要求“快速功能”。 嗨,伙计,你能给我举个这个不起作用的例子吗? :) 并且会附加列表理解解决方案,只是为了好玩。 aab 上试一试,它会给你[0, 0] 而不是[0, 1]。 (当然,OP 没有严格定义逻辑,也没有给我们提供大量样本测试,但似乎最有可能的是,正如所有其他答案所假设的那样,他希望 '' 在任何实际字符之前排序,因为那是照常做事。 对于列表理解:您可以直接将任何result = []; for foo in bar: result.append(baz(foo)) 转换为result = [baz(foo) for foo in bar]。所以,在你的情况下:result = [int(text1[index] == text2[index]) for index in range(min(len1, len2))]. @DSM:我根本没有提到排序,但实际上,排序两个字符和比较两个字符之间的区别只是你返回的内容。无论如何,这个问题的重点是比较。如果您无缘无故返回涉及比较的数字,则您返回的数字不正确。【参考方案3】:

你可以使用 numpy/pylab:

import pylab as p

a = p.fromstring("asdfg", dtype=p.int8)
b = p.fromstring("aqwer", dtype=p.int8)

print a == b

如果字符串的长度不同,您必须自己填充结果,如果需要,您还可以选择将布尔值数组转换为整数列表。

【讨论】:

+1。对于足够大的字符串,这可能是最快的解决方案,无需编写自己的 C(或至少 Cython)代码。 (对于小字符串,谁在乎呢?)并且可以很容易地自动完成两个缺失的步骤。有关示例,请参阅pastebin.com/dDu7S4Vp。 (显然,附加count NULs 而不是count-len(text) 有点浪费,但除非字符串很大,不会有太大区别,而且这种方式更简单一些。另外,我只使用了普通的numpy,因为我这台机器上没有pylab。)

以上是关于逐元素字符串比较的主要内容,如果未能解决你的问题,请参考以下文章

字符串字典序

来自逐元素逻辑比较的 MATLAB 逻辑矩阵的 Python 等效项

MySQL逐字节比较,哪个更快?二进制与 bin_collat​​e

超大字符串子集的比较

写一个strcmp函数,实现两个字符串的比较。 求注释。ORZ!

== 在 PHP 中是区分大小写的字符串比较吗?