2017-11-30 10 views
0

アカウントのリンク構造を指定する2つの列を持つCSVファイルがあります。 私が持っている問題は、これらのリンクごとに2つの逆のエントリがあることです。Python - 一意の値に基づいて検索、一致、並べ替え、追加する

Column1 Column2 
12513 52188 
52188 12513 

私も持っている他の問題は、あなたがすべてを見ることができるように同じアカウント番号にしてから、別のリンケージを指定する複数のエントリ

Column1 Column2 
12513 52188 
52188 12513 
52188 19922 
19922 52188 
19922 12812 
12812 19922 
18216 59888 
59888 18216 
3856 59888 
59888 3856 

があるかもしれないということですアカウントが何らかの形で相互にリンクされている場合、私が探している出力は、スレーブアカウントにリンクされた1つのマスターアカウント(おそらく最も低い値のアカウント)を作成し、2つの逆のエントリも削除する必要があります。上記のデータから

出力例:

Column1 Column2 
12513 52188 
12513 19922 
12513 12812 
3856 59888 
3856 18216 

ファイルは、 は1つのマスターアカウントだけでなくはありますのでご注意くださいと約2万行が含まれています。

+0

は不明である – RomanPerekhrest

+1

'gitのクローンます。https:// github.com/NiallCosgrove/kayboxa' –

+0

そのアップgithubの上今、コピー/貼り付けエラーを避けるためです。私は乱数の20000ペアでそれをテストし、1時間半かかる。 –

答えて

1

そこで質問です:ここ

1,2 
1,3 
1,4 
5,6 
5,7 

はPythonで実用的なソリューションであると形式のデータセット

1,2 
1,3 
1,4 
3,1 
6,5 
5,7 

考える
はチェーン1 -> 2 -> 3 -> 45 -> 6 -> 7 と出力それらを識別。 python thisfile.py yourdata.csv > output.csv

あなたを使用し、それを実行するには(ハッピーホリデー)

は、もちろん、のpython3をインストールする必要があります。 コードにはたくさんのコメントがあります。私は効率を全く考えなかったので、ケトルを入れてください。完了するまでに約15分かかります。

時間を要するlist.append()呼び出しが高速になりたい場合は、それを呼び出します。 numpyを使用すると処理が速くなりますが、余分な依存関係を追加したくありませんでした。

質問がある場合はお知らせください。あなたの例のデータから

出力は次のとおりです。

あなたは出力期待
3856 , 18216 
3856 , 59888 
12513 , 12812 
12513 , 19922 
12513 , 52188 
import csv 
import sys 


def flatten(l): 
    return list(set([item for subl in l for item in subl])) 

def main(): 
    # read the csv                      
    raw_data = [] 
    with open(sys.argv[1], 'r') as so_data: 
     lst = csv.reader(so_data) 
     for row in lst: 
      raw_data.append(row) 

     data = [] 
     for i in raw_data: 
      data.append([int(i[0].strip()), int(i[1].strip())]) 

     #set keys to uniq elements from col1 and col2             
     keys1 = list(set([i[0] for i in data])) 
     keys2 = list(set([i[1] for i in data])) 
     keys = list(set(keys1 + keys2)) 

     # find the subchains for each key                
     subchains = {} 
     for key in keys: 
      found = [k for k in data if key in k] 
      found = flatten(found) 
      subchains[key] = found 

     # This is the tricky bit                   
     # we need to follow each element of the subchains looking          
     # for new links - we are done for a key when the list doesn't grow        
     chain, links = [], [] 
     chain_dict = {} 
     for key in keys: 
      links.append(subchains[key]) 
      links = flatten(links) 
      done = False 
      size = len(links) 
      while not done: 
       for i in links: 
        # find subchain for i                
        for e in subchains[i]: 
         chain.append(e) 
         chain = list(set(chain)) 
         chain.sort() 
       if len(chain) > size: 
        done = False 
        size = len(chain) 
       else: 
        done = True 
        chain_dict[key] = chain 
        chain, links = [], [] 

     # shorter chains will now be subsets of longer ones            
     # and those can be discarded                  
     remove_list = [] 
     for i in keys: 
      for j in keys: 
       if set(chain_dict[j]) < set(chain_dict[i]): 
        remove_list.append(j) 

     remove_list = list(set(remove_list)) 
     for i in remove_list: 
      del chain_dict[i] 

     # remove duplicate values from dict                
     # it doesn't matter which key we remove               
     # since we only output from value                
     result = {} 
     for key, value in chain_dict.items(): 
      if value not in result.values(): 
       result[key] = value 

     # now output as per OP's request                 
     for k, v in result.items(): 
      v.sort() 
      for i in v[1:]: 
       print(v[0], ",", i) 

if __name__ == '__main__': 
    main() 
関連する問題