在python中创建一个循环

时间:2013-10-08 22:11:01

标签: python loops

我正在创建这样的搜索,就像在python中查询一样,收集id并使用像whois数据库那样的名称来解析它们。

所以我们说这是我在.txt文件中的数据

["81448068", "jimmy"]
["69711823", "bob"]
["92739493", "kyle, jimmy"]
["96399981", "kyle"]
["40112089", "john, peter"]
["79784393", "matthew, chad"]
["749968","bob, jimmy"]

Id位于左侧列,右侧是与之关联的名称。 我将如何使用某种类型的while或for循环来搜索该数据,直到所有名称完全匹配?如果添加了任何数据,这个方法应该有效,我会告诉你我目前的情况,但是在一个更大的txt文件中有更多的名字它不会起作用

def getNames(name):
    x = []
    f = open("names.txt","r") # that data up there represents names.txt
    for line in f.readlines():
        rid,names = json.loads(line.strip())
        if name in names:
           x += names.split(", ")
    return list(set(x))

我想将这些名称循环回到获取名称以获取与x中返回的名称相关联的更多名称,但是我必须手动添加另一个名称,因为有些类型的东西会循环这个直到找到与名称相关的所有匹配项?所以做getNames(“jimmy”)会返回,

["bob","jimmy","kyle"] 

然后它将检查与bob相关的所有名称,所有与之关联的名称,直到没有更多关联,并且它也会为jimmy和Kyle执行此操作。

所以基本上,它会搜索初始名称,在这种情况下让我们使用吉米。它返回与“jimmy”相关联的名称,然后它将搜索与之关联的每个单独的名称,所以让它说它返回,[“bob”,“jimmy”,“kyle”] 然后它将采取bob,在名称中搜索具有该名称的所有名称,然后搜索所有这些名称并搜索所有这些名称,直到它执行所有名称,然后它会做jimmy做同样然后去Kyle做相同。我可以用for来做到这一点但是,我需要添加多个fors,具体取决于我想要搜索的范围,我将如何进行一段时间以便它执行数据直到找到所有匹配项。

5 个答案:

答案 0 :(得分:2)

这非常有趣。我的基本策略是在处理文件时修复关联,而不是在事后进行搜索。我没有对它进行测试,但它应该可以工作,尽管有错误。

编辑:现在我已经测试了它。

档案names.txt

["81448068", "jimmy"]
["69711823", "bob"]
["92739493", "kyle, jimmy"]
["96399981", "kyle"]
["40112089", "john, kyle"]
["79784393", "matthew, chad"]
["749968"  , "bob, jimmy"]

处理文件:

import json

def process_new_file(filename, associations=None):
    if associations == None:
        associations = {}
    with open(filename, 'r') as f:
        lines = f.readlines()
    for line in lines:
        rid, onames = json.loads(line.strip())
        extras = set([x.strip() for x in onames.split(',')])
        names = set()
        while len(extras) > 0:
            names.update(extras)
            extras = set()
            for name in names:
                if not name in associations:
                    associations[name] = set()
                extras.update(associations[name] - names)
        for name in names:
            associations[name].update(names)
    return associations

if __name__ == '__main__':
    associations = process_new_file('names.txt')
    tmpl = '{:20}: {}'
    for person in associations:
        print tmpl.format(person, ', '.join(associations[person]))

输出:

jimmy               : jimmy, bob, john, kyle
chad                : matthew, chad
kyle                : jimmy, bob, john, kyle
matthew             : matthew, chad
bob                 : jimmy, bob, john, kyle
john                : jimmy, bob, john, kyle

答案 1 :(得分:1)

这是eval可能更合适的情况。 eval()基本上是说取一串文本并将其视为python代码。因此,由于您的输入文件采用python列表的格式,因此它将计算为列表。 (请注意,您可以如下所示迭代文件的行。)

def generateAssociations():
    associations = dict()

    f = open("names.txt","r")
    for line in f:
        line = eval(line)
        id = int(line[0])
        names = line[1].split(',')
        newNames = [name.strip() for name in names]

        for name in newNames:
            if name not in associations:
                associations[name] = lineNames
            else:
                associations[name] = associations[name] + newNames

    for key, value in associations.items():
        associations[key] = set(value)

    pprint.pprint(associations)

在您的示例数据上运行时,它会将其作为输出:

{'bob': {'jimmy', 'bob'},
'chad': {'matthew', 'chad'},
'jimmy': {'kyle', 'jimmy', 'bob'},
'john': {'john', 'peter'},
'kyle': {'jimmy', 'kyle'},
'matthew': {'matthew', 'chad'},
'peter': {'john', 'peter'}}

对于初级朋友来说,这是非常容易进一步扩展的。

答案 2 :(得分:1)

就解析文件而言,你做得很好。

至于搜索,你应该考虑改变你对整个主题的处理方式。 Python或任何语言都适用于实现业务逻辑,但在大多数情况下,它在搜索大数据存储方面并不是很好。所以如果你有1000个名字,Python会做一个不错的工作,但是一旦你开始进入1,000,000个名字,脚本就会爬到停止状态。

为了在大数据存储上进行有效搜索,这就是数据库的设计目标。因此,明智的方法是首先将txt文件中的所有数据转储到数据库中,然后根据需要进行查询。这将使您拥有最强大的解决方案,并允许您在将来轻松扩展它。如果你当前正在使用txt文件,你可能不需要一个完整的数据库,所以sqlite就足够了。如果您不知道Sqlite是单个文件中的完整SQL数据库。无需安装,无需配置,只需一个文件系统上的文件就可以了。 Python有一个很好的包装器,有很好的sqlite文档,所以如果你决定采用这条路线,那应该不是很困难。可以找到文档here。直接使用sqlite包装器的另一种方法是使用ORM(对象关系包装器),例如SQLAlchemy,但是如果您不熟悉数据库,并且因为您对数据库的使用会如此简单,我建议您只使用sqlite包装器直接。

答案 3 :(得分:1)

好的,这就是我的方法:(代码也可以在这里作为要点:https://gist.github.com/ychaouche/6894532

data = [
    ["81448068", "jimmy"],
    ["69711823", "bob"],
    ["92739493", "kyle, jimmy"],
    ["96399981", "kyle"],
    ["40112089", "john, kyle"],
    ["79784393", "matthew, chad"],
    ["749968"  , "bob, jimmy"],
]

class MetaPerson(type):
    _names_cache_ = {}
    def __call__(cls,name):
        return MetaPerson._names_cache_.setdefault(name,type.__call__(cls,name))

class Person(object):
    __metaclass__ = MetaPerson

    def __init__(self,name):
        self.name = name
        self.friends = []

    def __repr__(self):
        return "<Person '%s'>" % self.name

    def add_friend(self,person):
        if not person in self.friends : 
            self.friends.append(person)

        if self not in person.friends:
            person.add_friend(self)

    def get_network(self,depth_limit=-1):
        return [friend for friend in self.get_network_recursive(0,depth_limit,[self])]

    def get_network_recursive(self,actual_depth,depth_limit,network):
        if depth_limit != -1 and actual_depth > depth_limit:
            return

        if all((friend in network for friend in self.friends)):
            return

        for friend in self.friends :
            if not friend in network :
                yield friend
                network.append(friend)
                for friendsfriend in friend.get_network_recursive(actual_depth+1,depth_limit,network):
                    yield friendsfriend

class Population:
    def __init__(self):
        self.members = []

    def find(self,name):
        for member in self.members :
            if member.name == name :
                return member

    def add_member(self,person):
        if not person in self.members : 
            self.members.append(person)

    def __repr__(self):
        return repr(self.members)

def parse(data):
    population = Population()
    for tup in data :
        names   = tup[1].replace(" ","").split(",")
        # will return an existing person if name is already taken
        person1 = Person(names[0])
        # add_member won't add if already present        
        population.add_member(person1)
        if len(names) == 2 :
            # will return an existing person if name is already taken
            person2 = Person(names[1])
            # add_member won't add if already present
            population.add_member(person2)
            person2.add_friend(person1)
    return population

def main():
    population = parse(data)
    print "population",population
    kyle = population.find("kyle")
    print "Kyle's network : ",kyle.get_network(1)

def test():    
    antoine = Person("Antoine")
    johny   = Person("Johny")
    patrick = Person("Patrick")
    lisa    = Person("Lisa")

    johny.add_friend(antoine)
    antoine.add_friend(patrick)
    patrick.add_friend(lisa)
    johny.add_friend(lisa)
    print johny.get_network(1)


if __name__ == "__main__" :
    main()

这是输出

chaouche@karabeela ~/CODE/TEST/PYTHON $ python findnames.py
population [<Person 'jimmy'>, <Person 'bob'>, <Person 'kyle'>, <Person 'john'>, <Person 'matthew'>, <Person 'chad'>]
Kyle's network :  [<Person 'jimmy'>, <Person 'bob'>, <Person 'john'>]
chaouche@karabeela ~/CODE/TEST/PYTHON $

如果我将深度更改为0(仅表示即时朋友),则输出将更改为

chaouche@karabeela ~/CODE/TEST/PYTHON $ python findnames.py
population [<Person 'jimmy'>, <Person 'bob'>, <Person 'kyle'>, <Person 'john'>, <Person 'matthew'>, <Person 'chad'>]
Kyle's network :  [<Person 'jimmy'>, <Person 'john'>]
chaouche@karabeela ~/CODE/TEST/PYTHON $

答案 4 :(得分:0)

您可以输入以下内容创建无限循环:

 loop = "loop"
 while loop == "loop":
     ##your code here...

程序将永远循环while函数下面的任何内容。