使用惟一ID Python将2D列表中的所有元素替换为其他列表中的数据

2024-04-26 11:17:01 发布

您现在位置:Python中文网/ 问答频道 /正文

我对python还只有几个月的了解,所以请原谅代码太难看了。我有一个由唯一ID组成的数据集。请考虑这种格式,每行有3个ID:

zList = [[1412,2521,53522],
[52632,1342,1453],
[3413,342,25232]]

我试图用一些相应的数据(名字、姓氏、状态等)替换每个ID。理想输出如下所示:

resultList = [[Bob, Smith, Ohio, Jane, Doe, Texas, John, Smith, Alaska],
[Jim, Bob, California, Jack, White, Virginia, John, Smith, Nevada],
[Hank, Black, Kentucy, Sarah, Hammy, Florida, Joe, Blow, Mississipi]]

我意识到在结果中添加一个新维度会更干净,因为我实际上是在将每个ID扩展到一个新列表中。我之所以避免这样做,是因为我认为保持平面比较容易,而且我害怕迭代任何超过2维的东西!愿意考虑所有的选择。。。你知道吗

我用来匹配的数据是您可能期望的:

matchData = [[1412, Bob, Smith, Ohio, lots of additional data],
[2521, Jane, Doe, Texas, Lots of Additional Data],
[3411], Jim, Black, New York, Lots of Additional Data],
[...etc...]]

以下是我如何尝试的:

resultList = []
for i, valz in enumerate(zList):
    for j, ele in enumerate(valz):
        check = False
        for k, valm in enumerate(matchData):
            if ele == valm[0]:
                resultList.append(valm)
                check = True
                break
        if check == False:
            print "error during rebuild"
pprint.pprint(resultList, width=400)

现在,虽然它几乎工作,它缺少两个关键的东西,我不能'弄清楚。我的代码把所有东西都放到一个大列表里。我必须能够从原始数据集中保持顺序和逻辑分离。(请记住,原始数据集是3行3个ID)。你知道吗

我还需要抛出一个错误,如果没有找到匹配。您可以在上面的代码中看到我的尝试,但它不能正常工作。我尝试在我的第一个if语句后添加以下内容:

elif all(ele not in valm[15):
    check = False

但是我得到一个错误:"TypeError: argument of type 'int' is not iterable"


Tags: of数据代码inidfalseforif
2条回答

要获得更干净的代码,应该考虑使用类来封装数据。你知道吗

让我们看看:

class Person(object):
    def __init__(self, identifier, firstname, name, state):
        self.id = identifier
        self.firstname = firstname
        self.name = name
        self.state = state

    def __repr__(self):
        return "<{0} {1} (id : {2}) living in {3}>".format(self.firstname, self.name, self.id, self.state)

    def as_list(self):
        return [self.firstname, self.name, self.state]

class PersonList(list):
    def __init__(self, *args, **kwargs):
        list.__init__(self, *args, **kwargs)

    def getById(self, identifier):
        """ return the person of this list whose the id is equals to the requested identifier. """
        # filter(boolean function, iterable collection) -> return a collection hat contain only element that are true according to the function.
        # here it is used a lambda function, a inline function declaration that say for any given object x, it return x.id == identifier.
        # the list is filtered to only get element with attribut id equals to identifier. See https://docs.python.org/3.4/library/functions.html#filter
        tmp = list(filter(lambda x: x.id == identifier, self))
        if len(tmp)==0:
            raise Exception('Searched for a Person whose id is {0}, but no one have this id.'.format(identifier))
        elif len(tmp) > 1:
            raise Exception('Searched for a Person whose id is {0}, and many people seem to share this id. id are supposed to be unique.'.format(identifier))
        return tmp[0]

##CONSTANTS##   
#id list - modified to not instanciate 9 Person
ids = [[1412,2521,3411],#bob, jane, jim
        [3411,1412,1412],#jim, bob, bob
        [3411,2521,2521]]#jim, jane, jane

#person list 
index=PersonList([Person(1412, 'Bob', 'Smith', 'Ohio'),
         Person(2521, 'Jane', 'Doe', 'Texas'),
         Person(3411, 'Jim', 'Black', 'New York')])

def computeResult(id_list, personList): 
    personList = [ [personList.getById(identifier) for identifier in subList] for subList in id_list]

    resultList= []
    for sublist in personList:
        tmp = []
        for person in sublist:
            tmp += person.as_list()
        resultList.append(tmp)

    return resultList

if __name__ == "__main__":

    print(computeResult(ids, index))

因为我的观点是,你用一只手上的数据结构是错误的。应用程序应该处理Person对象之类的事情,而不是字符串列表。反正是你的应用程序。我只是建议您考虑使用personList作为处理数据的更好的数据结构,而不是这个丑陋的列表。 另一方面,如果id像我想的那样是唯一的,如果您成功地将数据放入字典中,例如

index={1412 : Person(...), 2500 : Person(...), ...}

或者

index={1412: ['Bob', 'Doe', ...], 2500 : [...], ...}` 

它确实更实用,因为您可以删除PersonList类,然后仅使用index.get(1412)来获取与id对应的数据

编辑:根据请求添加跟踪示例。你知道吗

此脚本保存在名为“”的文件中柔软的““

python3
>>> import sof
>>> sof.index
[<Bob Smith (id : 1412) living in Ohio>, <Jane Doe (id : 2521) living in Texas>, <Jim Black (id : 3411) living in New York>]
>>> sof.index.getById(666)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/home/vaisse/Bureau/sof.py", line 25, in getById
  raise Exception('Searched for a Person whose id is {0}, but no one have this id.'.format(identifier))
Exception: Searched for a Person whose id is 666, but no one have this id.

如你所见,一旦出错,一切都会停止。如果这种行为不是您想要的,您还可以返回一个None值,并在某个地方跟踪失败的内容,而不是增加一个Exception,然后继续处理数据。如果你想让你的应用程序在出错的情况下仍然运行,你应该看看https://docs.python.org/3.1/library/warnings.html。否则,提出一个简单的例外就足够了

我认为你的主要问题是名单的结构。从外观上看,zList中的每行和resultList中的每行都有3个“条目”。我建议将zList改为一维列表,并将results列表中的不同条目放在自己的列表中(在resultList中,如下所示:

zList = [ 1412, 2521, 53522, 52632, 1342, 1453, 3413, 342, 25232 ]
resultList = [[ "Bob", "Smith", "Ohio" ],[ "Jane", "Doe", "Texas" ],[ "John", "Smith", "Alaska" ],
          [ "Jim", "Bob", "California" ],[ "Jack", "White", "Virginia" ],[ "John", "Smith", "Nevada" ],               
          [ "Hank", "Black", "Kentucy" ],[ "Sarah", "Hammy", "Florida" ],[ "Joe", "Blow", "Mississipi"]]

现在您可以检查两个列表的长度是否相同(本例中为9):

>>> len(zList) == len(resultList
True
>>> len(zList)
9

从这里,你可以使用字典或列表。作为一个新手程序员,您可能还不熟悉字典,所以请查看the documentation。你知道吗

列表:

只需循环列表的长度,将其添加到newlist,然后将newlist附加到输出列表中,如下所示:

zList = [...]
resultList = [[...]]
matchList = [] #or whatever you want to call it

for i in range(len(zList)): #the index is needed, you can also use enumerate
    element_list = []
    element_list.append(zList[i]) #note zList[i] = 2nd iterator of enumerate
    for j in resultList[i]:  #the index is not needed, so use the value 
        element_list.append(j)
    matchList.append(elementList)

>>> print matchList
[1412, 'Bob', 'Smith', 'Ohio']
[2521, 'Jane', 'Doe', 'Texas']
[53522, 'John', 'Smith', 'Alaska']
[52632, 'Jim', 'Bob', 'California']
[1342, 'Jack', 'White', 'Virginia']
[1453, 'John', 'Smith', 'Nevada']
[3413, 'Hank', 'Black', 'Kentucy']
[342, 'Sarah', 'Hammy', 'Florida']
[25232, 'Joe', 'Blow', 'Mississipi'] #split in separate lines for clarity here

要添加更多数据,只需增加resultList中列表的大小,即可添加如下作业:

resultList = [[ "Bob", "Smith", "Ohio", "Tech Support" ], ...

词典

我认为这是最简单的方法。只需创建一个dict,然后使用zList中的元素与resultList中相应的元素组成键,如下所示:

matchDict = {}
for n in range(len(zList)): #need the index, remember?
    matchDict[zList[n]] = resultList[n]

>>> print matchDict
{ 1412 : ['Bob', 'Smith', 'Ohio'] ,
  1453 : ['John', 'Smith', 'Nevada'] ,
  25232 : ['Joe', 'Blow', 'Mississipi'] ,
  53522 : ['John', 'Smith', 'Alaska'] ,
  3413 : ['Hank', 'Black', 'Kentucy'] ,
  342 : ['Sarah', 'Hammy', 'Florida'] ,
  52632 : ['Jim', 'Bob', 'California'] ,
  2521 : ['Jane', 'Doe', 'Texas'] ,
  1342 : ['Jack', 'White', 'Virginia']  }

*注意,您可以使用字典中的键调用元素,因此print matchDict[1412]->;[“Bob”,“Smith”,“Ohio”]。同样,您可以通过向resultList添加更多信息来扩展数据,如上所示。你知道吗

相关问题 更多 >