2015-07-10 47 views
1

我只包含字符串兩套,我試圖寫這樣一個功能:Python的方式屬於功能兩套

def belongs(setA, setB): 
    return True/False 

定義:如果set,說setB有一個項目其中含有(string包含)setA中的一項,則我呼叫setB所屬的setA。一些例子:

setA = set(['apple', 'banana', 'strawberry']) 

set1 = set(['abcc', 'xyz', 'klm'])     # does not belong to setA 
set2 = set(['app', 'banaba', 'baba'])    # does not belong to setA 
set3 = set(['apples', 'xyz'])      # belongs to setA 
set4 = set(['bananaaa', 'hello', 'world', 'stack']) # belongs to setA 

我當前的代碼:

def belongs(set1, set2): 
    for i in set1: 
     for j in set2: 
      if i in j: 
       return True 
    return False 

是否有這樣做同樣的事情的一個更好/更Python的方式?

+0

是''set1'的set2'每一個字符串的子字符串,每次? – dlask

+0

@dlask一號就夠了。 – Sait

+0

您可能希望在不使用額外空間的情況下添加*,因爲如果我理解正確的話,您可以簡單*將* setA'變成一組物品。 – dhke

回答

4

編寫函數:

def belongs(set1, set2): 
    return any(s1 in s2 for s1 in set1 for s2 in set2) 

並對其進行測試:

assert not belongs(setA, set1) 
assert not belongs(setA, set2) 
assert belongs(setA, set3) 
assert belongs(setA, set4) 
+0

很酷的事實:這是一個[*生成器表達式*](https://docs.python.org/3.6/reference/expressions.html#grammar-token-generator_expression),而不是列表理解,這意味着它就像高效作爲原始的嵌套'for'循環。 (這些似乎並不是很知名。) – Lynn

+1

@Mauris我不會談論*列表理解*。 OP沒有提到*更高效的版本,只是更多的pythonic *版本。 – dlask

+0

哇,放鬆。我說「很酷的事實」。你的回答非常好。沒有很多人知道發生器表達式的優點,所以我想減輕任何人的擔憂,認爲這個答案可能比原來慢。 – Lynn

2

檢查從setA任何字符串是任何項目的setB子串的問題即是否setB「屬於「setA可以使用grep -F來解決。

grep -Flf setA set1 set2 set3 set4在這種情況下,「屬於」setA,即set3,set4的打印組。 Aho–Corasick string matching algorithm形成了原始Unix命令fgrep的基礎。對於大輸入而言,它比使用嵌套循環的簡單解決方案(例如from 20 hours for a brute-force approach down to a couple of minutes using fgrep)效率更高。

如果您不能安裝第三方庫;你可以嘗試re模塊,如果你需要它來提高性能:

import re 
from itertools import imap 

substrings = sorted(setA, key=len, reverse=True) # longest first 
found = re.compile("|".join(map(re.escape, substrings))).search 
print([any(imap(found, S)) for S in [set1, set2, set3, set4]]) 
# -> [False, False, True, True]