2012-11-21 2 views
5

文字列Sとlen(S)= len(L)のようなリストLの数字列があるとします。文字と数字の間の可能な双対を見つける

各文字が1桁に一致するように、文字列の文字とシーケンス内の数字との間に双射を見つけることができるかどうかを確認する最もクリーンな方法は何でしょうか。多分、

は例えば、「AABBCCは」115522と一致している必要がありますがありません123456または

111111私は2枚のdictsとループを持つ複雑なセットアップを持っていますが、これを行うためのクリーンな方法があります場合、私は思ったんだけどPythonライブラリのいくつかの関数を使用します。

+0

a = "abcabc"とb = "123127"の場合は、どのような出力が得られますか?真または偽 – raton

+0

偽です。 'c'は3と7の両方にマップされます(または、逆に3と7の両方が 'c'にマップされます)。バイジェクションでは、各要素は、もう1つのセットに1つだけの一致要素を持ちます。 –

答えて

6

私はこのためにセットを使用する:

In [9]: set("aabbcc") 
Out[9]: set(['a', 'c', 'b']) 

In [10]: set(zip("aabbcc", [1, 1, 5, 5, 2, 2])) 
Out[10]: set([('a', 1), ('c', 2), ('b', 5)]) 

とマッピングは全射である場合にのみ場合には、第2セットは第一の組に等しい長さを有するであろう。 (そうでない場合、あなたは第二セット、またはその逆に同じ番号に文字のマッピングの2つのコピーを持つことになります)

ここでは、これも返されますアイデア

def is_bijection(seq1, seq2): 
    distinct1 = set(seq1) 
    distinct2 = set(seq2) 
    distinctMappings = set(zip(seq1, seq2)) 
    return len(distinct1) == len(distinctMappings) and len(distinct2) == len(distinctMappings) 

を実装するコードです1つのシーケンスが他のシーケンスよりも短いが、有効なマッピングがすでに確立されている場合はtrueシーケンスの長さが同じでなければならない場合は、チェックを追加する必要があります。

+0

うーん、私はこれが動作するとは思わない? [1,1,1,1,1,1]では、(a、1)、(b、1)、(c、1)は3つの項目を持ちます。 これは、あなたに射撃を与えるものであり、完全な射撃ではありません。 –

+0

真。私は当初考えを提供しました。編集されたバージョンのコードは、両方のセットをチェックします。 – acjay

+0

クイック問題の質問は、 'a == b == c'が悪い習慣とみなされていますか? –

0
import itertools 

a = 'aabbcc' 
b = 112233 

z = sorted(zip(str(a), str(b))) 
x = all(
    gx == g0 
    for k, g in itertools.groupby(z, key=lambda x: x[0]) 
    for gx in g for g0 in g 
) 
print x 

か:

import itertools 

a = 'aabbcc' 
b = 112233 

z = zip(str(a), str(b)) 
x = all(
    (z1[0] == z2[0]) == (z1[1] == z2[1]) for z1 in z for z2 in z 
) 
print x 
0

あり(ソートやitertools.groupbyで)これを行うにはよりエレガントな方法ですが、私は寝る-deprovedする今それを把握するためにwayyです。しかし、これはまだ動作する必要があります

In [172]: S = "aabbcc" 

In [173]: L = [1, 1, 5, 5, 2, 2] 

In [174]: mapping = collections.defaultdict(list) 

In [175]: reverseMapping = collections.defaultdict(list) 

In [176]: for digit, char in zip(L, S): 
    mapping[digit].append(char) 
    reverseMapping[char].append(digit) 
    .....:  

In [177]: all(len(set(v))==1 for v in mapping.values()) and all(len(set(v))==1 for v in reverseMapping.values()) 
Out[177]: True 

In [181]: S = "aabbcc" 

In [182]: L = [1, 2, 3, 4, 5, 6] 

In [183]: mapping = collections.defaultdict(list) 

In [184]: reverseMapping = collections.defaultdict(list) 

In [185]: for digit, char in zip(L, S):                   
    mapping[digit].append(char) 
    reverseMapping[char].append(digit) 
    .....:  

In [186]: all(len(set(v))==1 for v in mapping.values()) and all(len(set(v))==1 for v in reverseMapping.values()) 
Out[186]: False 

希望これは

0

これを助けため尊重:あなたが正常にのみセット間の全単射について話しているので

>>> s = "aabbcc" 
>>> n = 115522 
>>> l1 = dict(zip(s, str(n))).items() 
>>> l2 = zip(s, str(n)) 
>>> l1 
[('a', '1'), ('c', '2'), ('b', '5')] 
>>> l2 
[('a', '1'), ('a', '1'), ('b', '5'), ('b', '5'), ('c', '2'), ('c', '2')] 
>>> not bool([i for i in l2 if i not in l1]) 
True 
>>> n = 115225 
>>> l1 = dict(zip(s, str(n))).items() 
>>> l2 = zip(s, str(n)) 
>>> not bool([i for i in l2 if i not in l1]) 
False 
0

を、私は他の回答とは異なり、想定し、数字の注文が文字の順序と一致する必要はないことを確認してください。その場合は、短くて洗練されたソリューションがありますが、Python 2.7で導入されたcollections.Counterクラスが必要です。古いバージョンのものには、backport for 2.5+があります。

from collections import Counter 

def bijection_exists_between(a, b): 
    return sorted(Counter(a).values()) == sorted(Counter(b).values()) 

テスト:あなたの質問を読んで別の方法が等しくなるように桁数や文字の数が可能になりますので

>>> bijection_exists_between("aabbcc", "123123") 
True 
>>> bijection_exists_between("aabbcc", "123124") 
False 

あなたの例はつまり、あなたが見て(、エッジケースにかなり軽いです一意の文字のセットから一意の数字のセットへの二乗のために、例えば"aabbcc""123333"にbijectするでしょう。

def bijection_exists_between(a, b): 
    return len(set(a)) == len(set(b)) 
+0

たぶん私は明確ではありませんでしたが、ちょっとした双射は双方向のマッピングです。あなたの最後の例では、 'a'は1と2の両方にマップされています。ここで3は 'b'と 'c'の両方に対応しているため、単射ではないだけでなく、投影的でも注入的でもありません。 –

+0

@EhsanKiaあなたは奇妙な方法で* bijection *という用語を使用しています。 Bijectionは2通りのマッピングですが、それは[sets](http://en.wikipedia.org/wiki/Set_(数学))の間にのみ存在します。文字列は重複する値を含む可能性があるため、セットではありません。あなたの質問に答えるためには、それを解釈する必要があります。私は完全に有効な解釈を2つ提示しました。私の最後の例は、 '' aabbcc ''({a、b、c})の文字の集合から' 123333'の{{1,2,3} })。 –

関連する問題