2011-09-21 4 views
1

많은 양의 구성 파일을 구문 분석하고 결과를 콘텐츠별로 별도의 그룹으로 그룹화하려고합니다.이 방법에 접근하는 방법을 모르겠습니다.일치 항목별로 그룹화

 
config1.txt 
ntp 1.1.1.1 
ntp 2.2.2.2 

config2.txt 
ntp 1.1.1.1 

config3.txt 
ntp 2.2.2.2 
ntp 1.1.1.1 

config4.txt 
ntp 2.2.2.2 
 
The results would be: 
Sets of unique data 3: 
Set 1 (1.1.1.1, 2.2.2.2): config1.txt, config3.txt 
Set 2 (1.1.1.1): config2.txt 
Set 3 (2.2.2.2): config4.txt 

내가 파일의 디렉토리, 루프 글로브 결과 glob에 한 번에 각 파일을 열고 일치하는 정규 표현식을 사용하는 방법을 이해 예를 들어, 내가 3 개 파일에 다음과 같은 데이터가 있다고 가정 해 각 라인. 필자가 이해할 수없는 부분은이 결과를 저장하고 각 파일을 일련의 결과와 비교하는 방법입니다. 항목이 잘못되었지만 일치 항목이 현명한 경우에도 마찬가지입니다. 어떤 도움을 주시면 감사하겠습니다.

감사합니다.

+1

은 쇼 "나는, 루프 글로브 결과를 파일의 디렉토리 glob에 한 번에 각 파일을 열고 각 라인에 맞게 정규식을 사용하는 방법을 이해하는"경우에 효율적이어야한다 우리는 그 코드를 작성하고 나머지는 어떻게 처리하는지 보여 드리겠습니다. 힌트 : 사전을 사용하십시오. – agf

답변

1

나는 이런 식으로이 문제를 접근하는 것 :

첫째,이 같은 사전 얻을 :

{(1.1.1.1) : (file1, file2, file3), (2.2.2.2) : (file1, file3, file4) } 

그런 다음 파일을 생성하는 동안 루프 세트 :

{(file1) : ((1.1.1.1), (2.2.2.2)), etc } 

다음은 비교 세트의 값.

if val(file1) == val(file3): 
    Set1 = {(1.1.1.1), (2.2.2.2) : (file1, file2), etc } 

이것은 아마도 가장 빠르지 만 우아한 해결책은 아니지만 작동해야합니다.

2
from collections import defaultdict 

#Load the data. 
paths = ["config1.txt", "config2.txt", "config3.txt", "config4.txt"] 
files = {} 

for path in paths: 
    with open(path) as file: 
     for line in file.readlines(): 
      ... #Get data from files 
      files[path] = frozenset(data) 

#Example data. 
files = { 
    "config1.txt": frozenset(["1.1.1.1", "2.2.2.2"]), 
    "config2.txt": frozenset(["1.1.1.1"]), 
    "config3.txt": frozenset(["2.2.2.2", "1.1.1.1"]), 
    "config4.txt": frozenset(["2.2.2.2"]), 
} 

sets = defaultdict(list) 

for key, value in files.items(): 
    sets[value].append(key) 

불변의 문자를 사용해야하므로 사전 키로 사용할 수 있습니다. 그들은 변화하지 않으므로 이것은 괜찮습니다.

+0

엎드려서, 나는 그것을 좋아한다. 나는 그것이 O (N * M)라고 생각합니다. 여기서 N은 파일의 수이고, M은 파일 당 구성 항목의 평균 수입니다. –

2
filenames = [ r'config1.txt', 
       r'config2.txt', 
       r'config3.txt', 
       r'config4.txt' ] 
results = {} 
for filename in filenames: 
    with open(filename, 'r') as f: 
     contents = (line.split()[1] for line in f) 
     key = frozenset(contents) 
     results.setdefault(key, []).append(filename) 
+1

나는 dict.setdefault보다 defaultdict (list)를 선호한다. – rocksportrocker

+0

나는 아마 그렇게해야하지만 최소한의 수입으로 할 수있는 모든 일을하려고하는 버릇이있다. –

+0

예, 가져 오기가 문제입니다 .. – rocksportrocker

1

파일 내용을 파일 이름에 매핑하는 사전이 필요합니다. 따라서 각 파일을 읽어야하고, 항목을 정렬하고, 튜플을 만들어 키로 사용하십시오.

파일에 중복 항목이있을 수있는 경우 : 내용을 먼저 set으로 읽습니다.

2

이 대안은 다른 것보다 자세한 내용이지만 두 가지 요인에 따라 더 효율적일 수 있습니다 (맨 끝의 내 노트 참조). 많은 수의 구성 항목이있는 많은 수의 파일을 처리하는 경우가 아니라면 다른 제안을 통해이 파일을 사용하는 것을 고려하지 않겠지 만 성능이 문제인 경우이 알고리즘이 도움이 될 수 있습니다. 파일 세트 (c2f를 호출하고, 파일에서. 모두 당신이 파일을 glob에로 구축 할 수 있습니다 설정 한 구성 문자열 (f2c)까지로 구성 문자열에서 사전에

시작.

하는 것은 할 수 clear, c2f는 키가 문자열이고 값이 파일 집합 인 사전입니다 f2c는 키가 파일이고 값이 문자열 집합 인 사전입니다

f2c 및 하나의 파일 키를 반복합니다. 데이터 항목. 해당 항목이 들어있는 모든 파일을 찾으려면 c2f를 사용하십시오.이 파일 만 비교해야합니다.

# this structure simulates the files system and contents. 
cfg_data = { 
    "config1.txt": ["1.1.1.1", "2.2.2.2"], 
    "config2.txt": ["1.1.1.1"], 
    "config3.txt": ["2.2.2.2", "1.1.1.1"], 
    "config4.txt": ["2.2.2.2"] 
} 

# Build the dictionaries (this is O(n) over the lines of configuration data) 
f2c = dict() 
c2f = dict() 

for file, data in cfg_data.iteritems(): 
    data_set = set() 
    for item in data: 
     data_set.add(item) 
     if not item in c2f: 
      c2f[item] = set() 

     c2f[item].add(file) 
    f2c[file] = data_set; 

# build the results as a list of pairs of lists: 
results = [] 

# track the processed files 
processed = set() 

for file, data in f2c.iteritems(): 
    if file in processed: 
     continue 

    size = len(data) 
    equivalence_list = [] 

    # get one item from data, preferably the one used by the smallest list of 
    # files. 
    item = None 
    item_files = 0 
    for i in data: 
     if item == None: 
      item = i 
      item_files = len(c2f[item]) 
     elif len(c2f[i]) < item_files: 
      item = i 
      item_files = len(c2f[i]) 

    # All files with the same data as f must have at least the first item of 
    # data, just look at those files. 
    for other_file in c2f[item]: 
     other_data = f2c[other_file] 
     if other_data == data: 
      equivalence_list.append(other_file) 
      # No need to visit these files again 
      processed.add(other_file) 

    results.append((data, equivalence_list)) 

# Display the results 
for data, files in results: 
    print data, ':', files 

계산 복잡도에 메모를 추가 : 여기

가 작동 코드의이 O N 파일의 개수 ((K 로그 N) * (L 로그 M)가) 기술적으로, M이다 (< = N)은 그룹의 수이고, 동일한 내용을 가진 파일의이고 L (< = M)은 각 L에 대해 쌍으로 비교해야하는 파일의 평균 수입니다 처리 된 파일. K < < N과 L < < M.