【问题标题】:Truncate Key Length in Python Dictionary截断 Python 字典中的键长度
【发布时间】:2014-06-03 14:25:23
【问题描述】:

我有一个 Python 字典,我正试图将它插入 mysql。问题是字典的键之一长于 64 个字符(mysql 中列的最大长度)。所以我需要将所有字典键截断为 64 个字符。

下面的代码在所有方面都有效,除了一个超过 64 个字符的键 = location_of_building_on_the_lot_if_garage_change_type_code_to_bgd_

data = {'x_coordinate': '1158020.73068669',
    'any_people_using_property_homeless_childen_gangs_': True,
    'police_district': '8',
    'location_of_building_on_the_lot_if_garage_change_type_code_to_bgd_': 'Front',
    'service_request_number': '14-00630589',
    'address_street_suffix': 'AVE',
    'y_coordinate': '1866585.99638448',
    'date_service_request_was_received': '2014-05-01T00:00:00',
    'address_street_number': '5719',
    'longitude': '-87.69612590561026',
    'latitude': '41.78965826126179',
    'address_street_name': 'FRANCISCO',
    'address_street_direction': 'S',
    'location': {'latitude': '41.78965826126179', 'needs_recoding': False, 'longitude': '-87.69612590561026'},
    'service_request_type': 'Vacant/Abandoned Building',
    'community_area': '63',
    'is_the_building_currently_vacant_or_occupied_': 'Vacant',
    'ward': '16',
    'is_building_open_or_boarded_': 'Open',
    'is_the_building_vacant_due_to_fire_': True,
    'zip_code': '60629'}


placeholders = ', '.join(['%s'] * len(data))
columns = ', '.join(data.keys())
sql = "INSERT INTO vacant_buildings (%s) VALUES (%s)" % (columns, placeholders)

我试图改变:

columns = ', '.join(data.keys())

columns = ', '.join(data[:64].keys())

但得到以下错误:TypeError: unhashable type

想法?

【问题讨论】:

    标签: python dictionary truncate


    【解决方案1】:

    您想截断键(=字符串),而不是数据(这是一个字典,没有“字符”意义上的“长度”):

    columns = ', '.join(d[:64] for d in data.keys())
    

    【讨论】:

      【解决方案2】:

      Pavel 的回答很好,但如果您担心由于截断而导致命名空间冲突

      例如,location_of_building_on_the_lot_if_garage_change_type_code_to_bgd_location_of_building_on_the_lot_if_garage_change_type_code_to_bgd_hahaha 将是不同的键,直到您截断它们,此时它们是相同的键。

      keys = []
      for k in data.keys():
          newKey = k[:64]
          count = 1
          while newKey in keys:
              alteration = str(count)
              newKey = newKey[:-len(alteration)] + alteration
              count += 1
          keys.append(newKey)
      
      columns = ', '.join(keys)
      

      【讨论】:

        【解决方案3】:

        虽然.join() 会解决这个问题,但它比这样做更慢:

        columns = ''
        for key in data.keys():
            columns += key[:64] +', '
        sql = "INSERT INTO vacant_buildings (%s) VALUES (%s)" % (columns[:-2], placeholders)
        

        这是因为 '.join()` 将对您已经迭代过的列表执行迭代操作,如果您正在处理大量数据集,手动完成这项工作会变得更快。

        另请注意,x[:-2] 适用于小型插入,但如果您将VALUES 捆绑在一起形成一个单执行字符串,如下所示:

        INSERT INTO table VALUES (1, 2, 3), (2,2,3), (3,2,3) ...
        

        执行data[:-2] 运算符会变得非常慢,其中计数器检查您是否在列表中的最后一项非常好,因此最后会跳过+', '

        如果您也打算去除值,请在一个 for 循环中执行此操作,而不是两个:

        for key, value in data.items():
            columns += key[:64] +', '
        

        为了与未来的 Python 版本兼容,也切换到.format() 而不是使用'something (%s) something else',因为这已经过时了。

        >>> a = [1, 2, 'test']
        >>> '{} is {} with {}'.format(*a)
        '1 is 2 with test'
        

        TL;DR:

        手动构建您的字符串,而不是使用多个迭代函数导致相同的结果。并使用.format()!!

        【讨论】:

          猜你喜欢
          • 2022-12-28
          • 1970-01-01
          • 2012-03-25
          • 2011-10-02
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2015-03-12
          • 1970-01-01
          相关资源
          最近更新 更多