1

IDを収集し、whoisデータベースのような名前でそれらを解析するPythonでクエリのようなこの検索を作成しています。

これが.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 で返される名前に関連付けられている名前をさらに取得したいのですが、手動で別の名前を追加する必要があります。いくつかのタイプの while があり、すべての一致が関連付けられるまでループします名前が見つかりましたか?getNames("jimmy") を実行すると、

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

次に、bob に関連付けられたすべての名前、それらに関連付けられたすべての名前を、関連付けがなくなるまでチェックし、jimmy と Kyle についても同じことを行います。

基本的にはイニシャル名で検索するので、今回はjimmyで検索します。「ジミー」に関連付けられた名前が返され、それに関連付けられた個々の名前が検索されるので、[「ボブ」、「ジミー」、「カイル」] が返されるとしましょう。次に、それらの名前をすべて検索し、すべての名前を実行するまでそれらの名前をすべて検索します。次に、ジミーが同じことを行い、次にカイルに行って同じことを行います。for を使用してこれを行うこともできますが、検索の範囲に応じて複数の for を追加する必要があります。すべての一致が見つかるまでデータを処理するには、しばらく時間がかかります。

4

5 に答える 5

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
于 2013-10-08T23:27:07.550 に答える
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 $
于 2013-10-09T01:07:25.830 に答える
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'}}

これは最初のレベルの友人向けですが、さらに拡張するのはかなり簡単なはずです。

于 2013-10-08T22:30:52.983 に答える