更新dicts位置字段数组

时间:2014-09-19 12:28:14

标签: python sorting dictionary

我有以下代码用于更新字典数组中的位置值。 当我更新一个对象的位置时,我想根据它们的值改变其他对象的位置。

items = [{'position': 0, '_id': 'Bob'}, {'position': 1, '_id': 'Tom'}, {'position': 2, u'_id': 'Sam'}]
data = {'_id': 'Tom', 'position': 2}

updated_items = []
for item in items:
    if item["_id"] == data["_id"]:
        item["position"] = data["position"]
        updated_items.append(item)
    elif item["position"] < data["position"]:
        updated_items.append(item)
    else:
        item["position"] += 1
        updated_items.append(item)

此代码的输出为:

updated_items = [{'position': 0, '_id': 'Bob'}, {'position': 2, '_id': 'Tom'}, {'position': 3, u'_id': 'Sam'}]

这是预期和正确的。但是,如果我要更新的对象位于位置0,则输出如下:

items = [{'position': 0, '_id': 'Bob'}, {'position': 1, '_id': 'Tom'}, {'position': 2, u'_id': 'Sam'}]
data = {'_id': 'Bob', 'position': 2}

updated_items = [{'position': 2, '_id': 'Bob'}, {'position': 1, '_id': 'Tom'}, {'position': 3, u'_id': 'Sam'}]

如何解决此问题并以更有效的方式执行此操作。

1 个答案:

答案 0 :(得分:0)

我确实要求进行后续评论,以消除可接受的输出类型的歧义。我认为这个问题可以解释一些问题。以下代码旨在处理未排序的列表。它将重新编号我们想要更新的字母位置范围和我们更改的位置之间的元素。此代码将在适当的方向上移动(这是因为我们可以更改为比我们更小或更大的位置)。

# Update the dictionary list entry matching the id in dictitem with a new position
def updatedictlist(dictlist, dictitem):

    # Get the dict item from the dict list matching the id in dictitem
    upditem = next(item for (index, item) in enumerate(dictlist) if item['_id'] == dictitem['_id'])

    # If there is a StopIteration exception then the dictitem position we 
    # are trying to update TO doesn't exist so we can go ahead and update
    # the dictitem with a new position without making any other changes.
    try:
        dstitem = next(item for (index, item) in enumerate(dictlist) \
                            if item['position'] == dictitem['position'])
    except StopIteration:
        # Update the dictlist and return the list.
        upditem['position'] = dictitem['position']
        return dictlist

    # We only want to update the values between range of values we care about
    # leaving the rest alone.
    rangelow, rangehigh = (min(upditem['position'], dstitem['position']), \
                           max(upditem['position'], dstitem['position']))

    # Since we are replacing a value it matters whether the destination is
    # ahead of us or behind us.
    direction = -1 if upditem['position'] - dstitem['position'] < 0 else 1

    # Shift the values that fall within the position range we are processing
    for item in dictlist:
        if (rangelow <= item['position'] <= rangehigh):
            item['position'] += direction

    # Finally process the dictitem we wanted to update
    upditem['position'] = dictitem['position']

    return dictlist

items = [{'position': 0, '_id': 'Bob'}, {'position': 1, '_id': 'Tom'}, {'position': 2, u'_id': 'Sam'}]
data = {'_id': 'Tom', 'position': 2}
print updatedictlist(copy.deepcopy(items), data)

data = {'_id': 'Bob', 'position': 2}
print updatedictlist(copy.deepcopy(items), data)

输出结果为:

[{'position': 0, '_id': 'Bob'}, {'position': 2, '_id': 'Tom'}, {'position': 1, u'_id': 'Sam'}]
[{'position': 2, '_id': 'Bob'}, {'position': 0, '_id': 'Tom'}, {'position': 1, u'_id': 'Sam'}]