2

此代码基于我收到的对此问题的优雅答案,并按比例放大以接受最多 5 个元素的嵌套列表。总体目标是合并在索引位置 1 具有重复值的嵌套列表。

当 marker_array 中的嵌套列表有 4 个元素时,异常传递会抑制 IndexError。但是代码未能在最终输出中包含 4 个元素列表之后的最后一个列表。我的理解是 defaultdict 的目的是首先避免 IndexErrors。

# Nested list can have 4 or 5 elements per list. Sorted by [1]
marker_array = [
    ['hard','00:01','soft','tall','round'],
    ['heavy','00:01','light','skinny','bouncy'],
    ['rock','00:01','feather','tree','ball'],
    ['fast','00:35','pidgeon','random'],
    ['turtle','00:40','wet','flat','tail']]  

from collections import defaultdict
d1= defaultdict(list)
d2= defaultdict(list)
d3= defaultdict(list)
d4= defaultdict(list)

# Surpress IndexError due to 4 element list.
# Add + ' ' because ' '.join(d2[x])... create spaces between words.
try:
    for pxa in marker_array:
        d1[pxa[1]].extend(pxa[:1])
        d2[pxa[1]].extend(pxa[2] + ' ')
        d3[pxa[1]].extend(pxa[3] + ' ')
        d4[pxa[1]].extend(pxa[4] + ' ')

except IndexError:
    pass

# Combine all the pieces.
res = [[' '.join(d1[x]),
        x,
        ''.join(d2[x]),
        ''.join(d3[x]),
        ''.join(d4[x])]
        for x in sorted(d1)]

# Remove empty elements.
for p in res:
    if not p[-1]:
        p.pop()

print res

输出几乎是我需要的:

[['hard heavy rock', '00:01', 'soft light feather ', 'tall skinny tree ', 'round bouncy ball '], ['fast', '00:35', 'pidgeon ', 'random ']]

由于我的技术水平,这个放大版肯定失去了一些原来的优雅。非常感谢任何有关改进此代码的一般指示,但我的两个主要问题按重要性排序是:

  1. 如何确保 ['turtle','00:40','wet','flat','tail'] 嵌套列表不被忽略?
  2. 我能做些什么来避免在“柔光羽毛”中出现尾随空白?
4

2 回答 2

3

问题是你的try块的位置。不是由 defaultdict 引起的,这IndexError是因为您试图在不存在pxa[4]的 4 行中访问。marker_array

将您的 try / except 移动到 for 循环内,如下所示:

for pxa in marker_array:
  try:
    d1[pxa[1]].extend(pxa[:1])
    d2[pxa[1]].extend(pxa[2] + ' ')
    d3[pxa[1]].extend(pxa[3] + ' ')
    d4[pxa[1]].extend(pxa[4] + ' ')
  except IndexError:
    pass

输出现在将包括第 4 行。

要回答您的第二个问题,您可以通过在每次加入''.join()时用 astrip()或呼叫包围各种呼叫来删除空格(例如.rstrip()strip(''.join(d2[x]))

于 2013-07-03T07:29:04.590 回答
2
  1. 因为您的 try 语句在 for 循环之外开始,所以 for 循环中的异常会导致程序转到 except 块并且之后不会返回循环。相反,将 try 放在循环内的 main 块之前:

    for pxa in marker_array:
        try:
            d1[pxa[1]].extend(pxa[:1])
            d2[pxa[1]].extend(pxa[2] + ' ')
            d3[pxa[1]].extend(pxa[3] + ' ')
            d4[pxa[1]].extend(pxa[4] + ' ')
    
        except IndexError:
            pass
    

    从技术上讲,在 try 块中包含尽可能少的代码是最佳做法,因此如果您确定列表中的项目永远不会少于 4 个,则可以在扩展 d4 之前将 try 块的开头移至该行.

  2. 如果我正确理解您的代码,您将得到尾随空格,因为您在 pxa[4] 之后添加了一个空格。当然,删除 d4[pxa[1]].extend(pxa[4] + ' ') 中的空间 d4[pxa[1]].extend(pxa[4]) 不会解决您的问题较短的列表。相反,您不能在 pxa[3] 之后添加一个空格,而是在 pxa[4] 之前添加一个空格,如下所示:

            d3[pxa[1]].extend(pxa[3])
            d4[pxa[1]].extend(' ' + pxa[4])
    

我认为这应该解决它。

于 2013-07-03T07:29:03.907 回答