【问题标题】:How can I split a 2D array into an array with unique values and a dictionary?如何将二维数组拆分为具有唯一值和字典的数组?
【发布时间】:2011-07-27 23:59:02
【问题描述】:

我正在尝试将二维数组拆分为特定格式,但不知道最后一步。我的数据样本结构如下:

# Original Data
fileListCode = [['Seq3.xls', 'B08524_057'], 
                ['Seq3.xls', 'B08524_053'], 
                ['Seq3.xls', 'B08524_054'],
                ['Seq98.xls', 'B25034_001'], 
                ['Seq98.xls', 'D25034_002'], 
                ['Seq98.xls', 'B25034_003']]

我正在尝试拆分它,使其看起来像这样:

# split into [['Seq3.xls', {'B08524_057':1,'B08524_053':2, 'B08524_054':3},
#             ['Seq98.xls',{'B25034_001':1,'D25034_002':2, 'B25034_003':3}]

字典键 1,2,3 基于条目的原始位置,从文件名第一次出现开始。为此,我首先创建了一个数组来获取所有唯一的文件名(任何 .xls 都是文件名)

tmpFileList = []
tmpCodeList = []
arrayListDict = []

# store unique filelist in a tempprary array:
for i in range( len(fileListCode)):
    if fileListCode[i][0] not in tmpFileList:
        tmpFileList.append( fileListCode[i][0]  )

但是,我正在为下一步而苦苦挣扎。我想不出一个好的方法来提取代号(例如B08524_052),然后将它们转换成一个字典,并根据它们的位置进行索引。

# make array to store filelist, and codes with dictionary values
for i in range( len(tmpFileList)):
    arrayListDict.append([tmpFileList[i], {}])

这段代码只产生[['Seq3.xls', {}], ['Seq98.xls', {}]];我不确定是否应该先生成结构然后尝试添加代码和字典值,或者是否有更好的方法。

-- 编辑:我只是通过更改 fileListCode 中的值使示例更加清晰@

【问题讨论】:

  • 您应该多描述一下 {'B08524_052':1,'B08524_053':2, 'B08524_054':3} 中的值的数字 1、2、3 是什么。
  • 谢谢。因此,数字 1,2,3 是某个文件名的组中出现的索引。顺便说一句,请注意 1,2,3 不是字典的键,而是值

标签: python arrays dictionary


【解决方案1】:

有了,itertools.groupby这个过程会简单很多:

>>> key = operator.itemgetter(0)
>>> grouped = itertools.groupby(sorted(fileListCode, key=key), key=key)
>>> [(i, {k[1]: n for n, k in enumerate(j, 1)}) for i, j in grouped]
[('Seq3.xls', {'B08524_052': 1, 'B08524_053': 2, 'B08524_054': 3}),
 ('Seq98.xls', {'B25034_001': 1, 'B25034_002': 2, 'B25034_003': 3})]

对于旧的 Python 版本:

>>> [(i, dict((k[1], n) for n, k in enumerate(j, 1))) for i, j in grouped]
[('Seq3.xls', {'B08524_052': 1, 'B08524_053': 2, 'B08524_054': 3}),
 ('Seq98.xls', {'B25034_001': 1, 'B25034_002': 2, 'B25034_003': 3})]

但我认为使用 dict 会更好:

>>> {i: {k[1]: n for n, k in enumerate(j, 1)} for i, j in grouped}
{'Seq3.xls': {'B08524_052': 1, 'B08524_053': 2, 'B08524_054': 3},
 'Seq98.xls': {'B25034_001': 1, 'B25034_002': 2, 'B25034_003': 3}}

【讨论】:

  • 哇。我只是想理解这一点;由于代码B....的位置很重要,并且代码发生了变化(例如C123...),这会影响字典条目的内容吗?
  • 是否可以在 Python 2.6.5 中使用这种语法?它使用 python 32 运行良好,但在 2.6.5 上它不起作用,我不太了解它,无法弄清楚要改变什么。
  • Python 2.7 附带了字典理解。但是您可以将其转换为生成器表达式或列表推导并手动调用 dict() ,例如:dict((k[1], n) for n, k in enumerate(j, 1))
  • 这行有问题:[(i, {k[1]: n for n, k in enumerate(j, 1)}) for i, j in grouped](我真的更喜欢 list/dict 组合。`
  • @celenius 将这一行写成如下使其更容易理解:[(duo0, {duo[1]: pos for pos, duo in enumerate(gr_of_duos, start=1)}) for duo0, gr_of_duos in grouped]
【解决方案2】:

您混淆了列表和字典。

做这样的事情会更有意义:

file_list_code = [['Seq3.xls', 'B08524_052'],
                  ['Seq3.xls', 'B08524_053'],                  
                  ['Seq3.xls', 'B08524_054'],                 
                  ['Seq98.xls', 'B25034_001'],                  
                  ['Seq98.xls', 'B25034_002'],                  
                  ['Seq98.xls', 'B25034_003']] 

file_codes = {}
for name, code in file_list_code:
    if name not in file_codes:
        file_codes[name] = []
    file_codes[name].append(code)

这会产生:

{'Seq3.xls': ['B08524_052', 'B08524_053', 'B08524_054'], 
'Seq98.xls': ['B25034_001', 'B25034_002', 'B25034_003']}

这可以通过使用 defaultdict 进一步简化。对于这么简单的事情,可以说是矫枉过正,但很高兴知道。这是一个例子:

import collections

file_list_code = [['Seq3.xls', 'B08524_052'],
                  ['Seq3.xls', 'B08524_053'],                  
                  ['Seq3.xls', 'B08524_054'],                 
                  ['Seq98.xls', 'B25034_001'],                  
                  ['Seq98.xls', 'B25034_002'],                  
                  ['Seq98.xls', 'B25034_003']] 

file_codes = collections.defaultdict(list)
for name, code in file_list_code:
    file_codes[name].append(code)

【讨论】:

  • 感谢您的解释。我仍然需要字典格式的第二部分,以便以后查找。
  • @celenius - 您的字典值似乎只是索引......在这种情况下,列表要简单得多,并且完成完全相同的事情。 (例如file_codes[filename].index('B25034_002'))。
  • 我需要稍后获取代码的位置,因为列表很大,我认为字典是最好的。
  • @celenius - 更好的是相对的。列表固有地存储顺序,但在列表中查找索引是线性时间操作。查找给定字典键的值会更快(恒定时间),但是字典会占用更多内存并且构造起来更复杂。就个人而言,除非有充分的理由不这样做,否则我会坚持列出清单。打电话somelist.index(...) 真的是瓶颈吗?当然,这也部分是个人喜好。
【解决方案3】:
fileListCode = [['Seq3.xls', 'B08524_052'],
                ['Seq3.xls', 'B08524_053'],
                ['Seq3.xls', 'B08524_054'],
                ['Seq98.xls', 'B25034_001'],
                ['Seq98.xls', 'B25034_002'],
                ['Seq98.xls', 'B25034_003']]

dico = {}
li = []
for a,b in fileListCode:

    if a in dico:
        li[dico[a]][1][b] = len( li[dico[a]][1] ) + 1


    else:
        dico[a] = len(li)
        li.append([a,{b:1}])


print '\n'.join(map(str,li))

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-08-19
    • 2021-02-02
    • 2023-03-08
    • 2016-08-10
    • 2022-07-06
    • 2011-07-24
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多