2011-09-21 72 views
1

我想解析大量的配置文件,并根据内容将结果分组到不同的组 - 我只是不知道如何处理这个问题。例如,假设我有3个文件以下数据:通过匹配集分组项目

 
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的文件的目录,循环水珠结果并打开每次打开一个文件,并使用正则表达式匹配每一行。我不明白的部分是,如何将这些结果存储起来,并将每个文件与一组结果进行比较,即使条目不符合条件,但是明智地匹配条目也是如此。任何帮助,将不胜感激。

谢谢!

+1

“我明白如何glob文件目录,循环glob结果并一次打开每个文件,并使用正则表达式匹配每一行”show我们的代码,我们很乐意告诉你如何去做其余的事情。提示:使用字典。 – 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) 

请注意,您需要使用frozensets,因为它们是不可变的,因此可以用作字典键。由于他们不会改变,这很好。

+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,并从文件设置配置字符串(f2c)。两者都可以作为你glob的文件建立一个字典。

要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((K数N)*(L日志M)),其中N为文件的数量,M是(< = N)是具有相同内容和L的文件的组的数量 L(< = M)是必须成对比较的每个L的文件的平均数量处理文件。这应该是有效的,如果K < < N和L < < M.