1

我有这个代码:

from BeautifulSoup import BeautifulSoup

TABLE_CONTENT = [['958','<a id="958F" href="javascript:c_row(\'958\')" title="go to map"><img src="/images/c_map.png" border="0"></a>','USA','Atmospheric','<a href="javascript:c_ol(\'958\')" title="click date time to show origin_list (evid=958)">1945/07/16 11:29:45</a>','33.6753','-106.4747','','-.03','21','','','TRINITY','&nbsp;','&nbsp;','<a href="javascript:c_md(\'958\')" title="click here to show source data">SourceData</a>','&nbsp;'],['959','<a id="959F" href="javascript:c_row(\'959\')" title="go to map"><img src="/images/c_map.png" border="0"></a>','USA','Atmospheric','<a href="javascript:c_ol(\'959\')" title="click date time to show origin_list (evid=959)">1945/08/05 23:16:02</a>','34.395','132.4538','','-.58','15','','','LITTLEBOY','&nbsp;','&nbsp;','<a href="javascript:c_md(\'959\')" title="click here to show source data">SourceData</a>','&nbsp;']]

EVENT_LIST = []
for EVENT in TABLE_CONTENT:
    events = {}
    for index, item in enumerate(EVENT):
        if index == 0:
            events['id'] = item
        if index == 4:
            soup = BeautifulSoup(item)
            for a in soup.findAll('a'):
                events['date'] = ''.join(a.findAll(text=True))
        if index == 2:
            events['country'] = item
        if index == 3:
            events['type'] = item
        if index == 5:
            events['lat'] = item
        if index == 6:
            events['lon'] = item
        if index == 8:
            events['depth'] = item
        if index == 9:
            events['yield'] = item
        if index == 12:
            events['name'] = item
    sorted(events, key=lambda key: events['id'])
    EVENT_LIST.append(events)
    print '=== new record ==='
EVENT_LIST.sort(key=lambda x: x['id'])
print EVENT_LIST

我遇到的第一个问题是,在 EVENT_LIST 中,字典对象的顺序与它们添加到列表中的顺序不同,例如,当我打印结果时,'lat' 和 'lon' 不是按顺序排列的:

[{'name': 'TRINITY', 'country': 'USA', 'lon': '-106.4747', 'yield': '21', 'lat': '33.6753', 'depth': '-.03', 'date': u'1945/07/16 11:29:45', 'type': 'Atmospheric', 'id': '958'}, {'name': 'LITTLEBOY', 'country': 'USA', 'lon': '132.4538', 'yield': '15', 'lat': '34.395', 'depth': '-.58', 'date': u'1945/08/05 23:16:02', 'type': 'Atmospheric', 'id': '959'}]

还有更好的方法来编写这段代码吗?

4

5 回答 5

1

https://stackoverflow.com/a/526131/735204

字典根据定义是无序的,因为它们在内部存储为哈希表。缺少排序是从哈希表中插入和删除键的算法的结果。因此,您永远不应该依赖字典的键以任何特定顺序。也许考虑使用元组或字典列表 - 后者将允许您维护键:值格式,同时还保证可靠的排序。

如果您真的打算使用字典,您可能还想查看 OrderedDict,尽管恕我直言,如果您使用字典并要求对其进行排序,那么您正在以错误的方式考虑数据,并且可能存在更简单的方法来做到这一点。http://docs.python.org/library/collections.html#collections.OrderedDict

对于好奇的人来说,这是一个很好的演示文稿,准确解释了 Python 字典为什么具有未定义的排序http://blip.tv/pycon-us-videos-2009-2010-2011/pycon-2010-the-mighty-dictionary- 55-3352147

于 2012-08-21T17:12:16.537 回答
1

您可以使用OrderedDict容器保留插入字典的顺序。从手册:

返回一个 dict 子类的实例,支持常用的 dict 方法。OrderedDict 是一个 dict,它记住第一次插入键的顺序。如果新条目覆盖现有条目,则原始插入位置保持不变。删除条目并重新插入会将其移至末尾。

此功能仅在 2.7 版本后才出现。

@更好的方法:您可能会在之后更改if index == ...elif index == ...因为如果索引为 2,则它永远不会是 5。或者您可以存储索引/键组合并使用它们来存储您的项目。示例(未尝试):

combos={
        0: 'id',
        2: 'country',
        3: 'type',
        5: 'lat',
        6: 'lon',
        8: 'depth',
        9: 'yield',
        12: 'name' }

...

for index, item ...:
    if index == 4:
        soup = BeautifulSoup(item)
        for a in soup.findAll('a'):
        events['date'] = ''.join(a.findAll(text=True))
    elif index in combos:
        events[combox[index]]=item

我想你应该已经明白了。

于 2012-08-21T17:13:18.333 回答
0

Python 中的字典默认是无序的。

您可以改用OrderedDict。请注意,这仅在 Python 2.7+ 中可用

于 2012-08-21T17:13:58.577 回答
0

更好的转换代码:

from BeautifulSoup import BeautifulSoup

HEADERS = ['id', None, 'country', 'type', 'date', 'lat', 'lon', None, 'depth', 'yield', None, None, 'name']
TABLE_CONTENT = [['958','<a id="958F" href="javascript:c_row(\'958\')" title="go to map"><img src="/images/c_map.png" border="0"></a>','USA','Atmospheric','<a href="javascript:c_ol(\'958\')" title="click date time to show origin_list (evid=958)">1945/07/16 11:29:45</a>','33.6753','-106.4747','','-.03','21','','','TRINITY','&nbsp;','&nbsp;','<a href="javascript:c_md(\'958\')" title="click here to show source data">SourceData</a>','&nbsp;'],['959','<a id="959F" href="javascript:c_row(\'959\')" title="go to map"><img src="/images/c_map.png" border="0"></a>','USA','Atmospheric','<a href="javascript:c_ol(\'959\')" title="click date time to show origin_list (evid=959)">1945/08/05 23:16:02</a>','34.395','132.4538','','-.58','15','','','LITTLEBOY','&nbsp;','&nbsp;','<a href="javascript:c_md(\'959\')" title="click here to show source data">SourceData</a>','&nbsp;']]

EVENT_LIST = []
for EVENT in TABLE_CONTENT:
    events = {}
    for index, item in enumerate(EVENT):
        if index != 4:
            events[HEADERS[index]] = item
        if index == 4:
            soup = BeautifulSoup(item)
            for a in soup.findAll('a'):
                events[HEADERS[index]] = ''.join(a.findAll(text=True))
    sorted(events, key=lambda key: events['id'])
    EVENT_LIST.append(events)
    print '=== new record ==='
EVENT_LIST.sort(key=lambda x: x['id'])
print EVENT_LIST
于 2012-08-21T17:17:11.627 回答
0

首先是关于您的代码的一些评论:

  1. events如果它在循环中,为什​​么要调用它?它只有一个event
  2. 为什么要events为不同的事件重用变量?例如,如果事件格式错误,例如没有项目,这可能很危险
  3. sorted在您的代码中是无操作的,它没有副作用
  4. 为什么将 CAPITAL 用于非常量变量?

字典上的问题不是真正的问题,而是一个特性:键是按其哈希排序的,因为dict它是基于哈希的。如果您确实需要保存订单,您可以使用collections.OrderedDict

顺便说一下,这里有一个例子:

import operator

event_list = []
for event in TABLE_CONTENT:
    event_dict = {}
    event_dict['id'] = event[0]
    event_dict['country'] = event[2]
    # ...
    event_dict['name'] = event[12]
    event_list.append(event_dict)
event_list = sorted(event_list, key = operator.itemgetter('id'))
print event_list
于 2012-08-21T17:24:01.873 回答