根据内部参数之一删除(或替换)multi-level 列表中的项目

Remove (or replace) items in a multi-level list based on one of the parameters inside

population=[[[0, 0, 1, 0, 1, 1, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1], [4], [0]],
[[0, 0, 1, 1, 1, 0, 0, 1, 1, 0, 1, 1, 0, 0, 0, 1], [3], [1]],
[[0, 1, 1, 0, 1, 1, 0, 0, 1, 1, 1, 0, 0, 1, 0, 0], [4], [2]],
[[1, 0, 0, 1, 1, 1, 0, 0, 1, 1, 0, 1, 1, 0, 0, 0], [1], [3]]]    

selected_chromosomes=[[[0, 1, 1, 0, 1, 1, 0, 0, 1, 1, 1, 0, 0, 1, 0, 0], [5], [2]],
[[0, 0, 1, 0, 1, 1, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1], [3], [0]]]

child1=[0, 1, 1, 0, 1, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0]
child2=[0, 0, 1, 0, 1, 1, 0, 1, 1, 1, 1, 0, 0, 1, 0, 1]   



def PopulationAdjustment(population, selected_chromosomes):
    for game in range(0, len(selected_chromosomes)):
        if game in selected_chromosomes[game][2]==game in population[game][2]: 
            population.remove(game)
    return population  

所以这里的 objective 是用人口(列表)中的 children 替换 parents,我的方法是删除 parents 然后附加children,基于同一个计数器。列表的结构是 [[chromosome],[fitness],[counter]],但是它们并不完全相同,因为我在选择过程中操纵了适应度以避免 0 概率。

我正在尝试索引具有相同计数器的项目并将它们从列表中删除,那么下一步就是 append children。

我一直在尝试一些不同的方法,但我无法让它正常工作,关于如何解决这个问题有什么想法吗?此外,如果有一种方法可以直接用 children 替换它们而无需执行 2 个步骤(删除和附加),那将非常受欢迎。谢谢!!

你说的是"I am trying to index the items that have the same counter and delete them from the list"。虽然这是可能的,但构建一个包含您想要保留的染色体的新列表更容易(也更快),除非 population 很大。

我们首先扫描 selected_chromosomes 以将它们的计数器编号提取到一个集合中,以便我们可以快速查找它们。

population=[
    [[0, 0, 1, 0, 1, 1, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1], [4], [0]],
    [[0, 0, 1, 1, 1, 0, 0, 1, 1, 0, 1, 1, 0, 0, 0, 1], [3], [1]],
    [[0, 1, 1, 0, 1, 1, 0, 0, 1, 1, 1, 0, 0, 1, 0, 0], [4], [2]],
    [[1, 0, 0, 1, 1, 1, 0, 0, 1, 1, 0, 1, 1, 0, 0, 0], [1], [3]],
]

selected_chromosomes=[
    [[0, 1, 1, 0, 1, 1, 0, 0, 1, 1, 1, 0, 0, 1, 0, 0], [5], [2]],
    [[0, 0, 1, 0, 1, 1, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1], [3], [0]],
]

def population_adjustment(population, selected_chromosomes):
    # Create a set of the counter numbers to remove
    drop = {u[-1][0] for u in selected_chromosomes}

    # Copy the wanted chromosomes to a new list
    return [u for u in population if u[-1][0] not in drop]

new_pop = population_adjustment(population, selected_chromosomes)
for row in new_pop:
    print(row)

输出

[[0, 0, 1, 1, 1, 0, 0, 1, 1, 0, 1, 1, 0, 0, 0, 1], [3], [1]]
[[1, 0, 0, 1, 1, 1, 0, 0, 1, 1, 0, 1, 1, 0, 0, 0], [1], [3]]

如果 population 列表 巨大的,或者您有其他原因保留原始列表(例如,在不同的地方有多个引用) ,这是删除不需要的列表的方法。不过,我们必须小心。从您正在迭代的列表中删除项目是危险的,因为删除会扰乱剩余列表项目的索引,如 here 所示。这有点像砍掉你坐在上面的树枝。如果你在错误的地方切入,坏事就会发生。 ;) 最简单的方法是反向迭代列表。

population=[
    [[0, 0, 1, 0, 1, 1, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1], [4], [0]],
    [[0, 0, 1, 1, 1, 0, 0, 1, 1, 0, 1, 1, 0, 0, 0, 1], [3], [1]],
    [[0, 1, 1, 0, 1, 1, 0, 0, 1, 1, 1, 0, 0, 1, 0, 0], [4], [2]],
    [[1, 0, 0, 1, 1, 1, 0, 0, 1, 1, 0, 1, 1, 0, 0, 0], [1], [3]],
]

selected_chromosomes=[
    [[0, 1, 1, 0, 1, 1, 0, 0, 1, 1, 1, 0, 0, 1, 0, 0], [5], [2]],
    [[0, 0, 1, 0, 1, 1, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1], [3], [0]],
]

def population_adjustment(population, selected_chromosomes):
    # Create a set of the counter numbers to remove
    drop = {u[-1][0] for u in selected_chromosomes}

    # Iterate backwards over population so we can safely delete sublists
    for i in range(len(population)-1, -1, -1):
        k = population[i][-1][0]
        if k in drop:
           del population[i] 

    # Since we mutate `population` we should return `None`, as is conventional in Python.
    # This return statement isn't necessary, since `None` is the default return value,
    # but it's nice to be explicit
    return None

population_adjustment(population, selected_chromosomes)
for row in population:
    print(row)

这段代码产生的输出与之前的版本相同,所以我不再重复。