Показать сообщение отдельно
Старый 19.07.2013, 17:08
trashcoder вне форума Посмотреть профиль Отправить личное сообщение для trashcoder Найти все сообщения от trashcoder
  № 6  
Ответить с цитированием
trashcoder

Регистрация: Jul 2012
Сообщений: 10
Записей в блоге: 1
Ключевой момент тут:
Цитата:
Сообщение от trashcoder Посмотреть сообщение
На добавление/удаление при этом вызвать коллбек. Сначала все удалить, потом по порядку добавить, ума много не надо.
Нужно знать, какие элементы добавились, а какие удалились. Даже желательно еще узнать, какие поменяли индекс. Очистить, а затем заполнить массив я бы сумел (хоть и не додумался бы до решения в одну строку).
Решение в лоб: сначала найти элементы одного, отсутствующие в другом, и наоборот, вызвать для каждого соответствующую функцию, потом уже изменить массив, но этого я хотел избежать.
Ночью приснилось, как решить это рекурсивно. Вот что набросал на Питоне:
Код:
def added_handler(element, index):
    print("element '" + str(element) + "'\tadded at index", str(index))

def removed_handler(element, index):
    print("element '" + str(element) + "'\tremoved from index", str(index))

def moved_handler(element, index):
    print("element '" + str(element) + "'\tmoved to index", str(index))

def sync_arrays(source, target, on_added = None, on_removed = None, on_moved = None):
    def added(element, index):
        if on_added and element != None:
            on_added(element, index)

    def removed(element, index):
        if on_removed and element != None:
            on_removed(element, index)

    def moved(element, index):
        if on_moved and element != None:
            on_moved(element, index)

    def recursive_permutation(element):
        # element added
        if element in source and element not in target:
            index_in_source = source.index(element)
            added(element, index_in_source)
            replaced_by_element = target[index_in_source]
            target[index_in_source] = element
            recursive_permutation(replaced_by_element)
        # element removed
        elif element not in source and element in target:
            index_in_target = target.index(element)
            removed(element, index_in_target)
            replacing_element = source[index_in_target]
            recursive_permutation(replacing_element)
        # element moved
        elif element in source and element in target:
            index_in_source = source.index(element)
            index_in_target = target.index(element)
            if(index_in_source == index_in_target):
                return
            replaced_by_element = target[index_in_source]
            replacing_element = source[index_in_target]
            target[index_in_source] = element
            moved(element, index_in_source)
            if replaced_by_element == replacing_element:
                target[index_in_target] = replacing_element
                moved(replaced_by_element, index_in_target)
            else:
                recursive_permutation(replacing_element)
                recursive_permutation(replaced_by_element)

    # get rid of out of range error
    while len(target) < len(source):
        target.append(None)
    for i in range(0, len(source)):
        # all ok
        if target[i] == source[i]:
            continue
        # something different
        recursive_permutation(target[i])
    # remove rest garbage
    while i < len(target) - 1:
        removed(target.pop(), len(target))
    return target

if __name__ == "__main__":
    source = [18, 19, 1, 2, 4, 6, 8, 32, 3, 200, 42, 12, 99]
    target = [19, 18, 2, 3, 1, 8, 200, 12, 666, 32, 111, 222, 333, 444, 555]
    sync_arrays(source, target, added_handler, removed_handler, moved_handler)
    print("source", source)
    print("target", target)
Код кривоват, но результат удовлетворительный:
Код:
element '19'	moved to index 1
element '18'	moved to index 0
element '2'	moved to index 3
element '1'	moved to index 2
element '4'	added at index 4
element '3'	added at index 8
element '8'	moved to index 6
element '6'	added at index 5
element '200'	added at index 9
element '32'	added at index 7
element '12'	added at index 11
element '111'	removed from index 10
element '42'	added at index 10
element '333'	removed from index 12
element '99'	added at index 12
element '555'	removed from index 14
element '444'	removed from index 13
source [18, 19, 1, 2, 4, 6, 8, 32, 3, 200, 42, 12, 99]
target [18, 19, 1, 2, 4, 6, 8, 32, 3, 200, 42, 12, 99]
В общем, переведу это на as3 и буду дальше дорабатывать напильником, но вопрос о лучшем и самом быстром решении остается в силе.
По-моему, это достаточно полезная функция, когда можно узнать, что именно изменять во вьюхе при произвольном изменении модели, вместо того, чтобы инициализировать все подряд.


Последний раз редактировалось trashcoder; 22.07.2013 в 01:55. Причина: исправил код