当前位置: 首页 > 知识库问答 >
问题:

我如何在每次迭代中成对地组合list元素而不重复?

太叔景曜
2023-03-14
lst = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] 

此外,在每个迭代中,个体随机配对,例如:

[1, 5], [7, 10], [3, 4], [6, 8], [2, 9]

并且这些配对有可能会有一个子,它将作为下一个数字(11,12等)添加到列表中

每一对可能只出现一次,所以我必须存储每一对,在随机选择两个个体后,检查他们是否已经是一对了。

reproducing_prob = 0.1 #probability of reproduction
death_prob = 0.1 #probability of death
pop_size = 10 #starting population size
pop_start = list(range(1, pop_size+1))
used_pairs = set() #storing pairs that already appeared
new_creature = 10

for day in range(10):
    
    print("\nDay ", day)
    print("Population: ", pop_start)
    dead_creatures = []
    
    for creature in pop_start: #iterating through whole list to check if creatures die
        death = np.random.uniform(0,1)
        if death < death_prob:
            print("Dead: ", creature)
            dead_creatures.append(creature)  
            
    pop_start = [creature for creature in pop_start if creature not in dead_creatures]

    pop_temp = pop_start.copy()
    while len(pop_temp) > 1: #looping through list until there aren't enough elements to pair them up
        idx1, idx2 = random.sample(range(0, len(pop_temp)), 2) 
        rand1, rand2 = pop_temp[idx1], pop_temp[idx2] 
        print("Found pair: ", rand1, rand2)
        
        if ((rand1, rand2) not in used_pairs) and ((rand2, rand1) not in used_pairs): #check if random pair hasn't been already used
            for i in sorted([idx1, idx2], reverse=True):
                pop_temp.pop(i)
            pair = rand1, rand2
            used_pairs.add(pair)
            reproducing = np.random.uniform(0,1)
            if reproducing < reproducing_prob:
                pop_size += 1
                new_creature += 1
                print("New creature! ", new_creature)
                pop_start.append(new_creature)
Day  0
Population:  [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
Found pair:  10 3
Found pair:  7 5
New creature!  11
Found pair:  8 2
Found pair:  9 1
Found pair:  6 4

Day  1
Population:  [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]
Dead:  8
Found pair:  6 10
Found pair:  1 11
Found pair:  4 5
Found pair:  2 9
Found pair:  3 7

Day  2
Population:  [1, 2, 3, 4, 5, 6, 7, 9, 10, 11]
Dead:  6
Found pair:  5 11
Found pair:  10 1
Found pair:  3 2
Found pair:  9 7

Day  3
Population:  [1, 2, 3, 4, 5, 7, 9, 10, 11]
Found pair:  11 9
Found pair:  4 7
Found pair:  5 10
Found pair:  2 1

Day  4
Population:  [1, 2, 3, 4, 5, 7, 9, 10, 11]
Dead:  10
Found pair:  5 3
New creature!  12
Found pair:  2 7
Found pair:  9 1
Found pair:  4 9
Found pair:  1 11
Found pair:  11 1
Found pair:  1 11
Found pair:  11 1

共有1个答案

季凡
2023-03-14

由于成对的生成器在调用之间是有状态的,所以我将把这个功能包装在类中。该实例将存储使用过的对,以确保我们不会重复任何内容。使用itertools.compositions,我们可以找到所有可能的对。我们可以随机取样这些组合,然后跟踪我们在那一轮中使用的所有个体。

class PairGenerator:
    def __init__(self):
        self.used_pairs = set()

    def next_pairs(self, individuals):
        """
        Return unique pairs of individuals that haven't been seen before.
        In each call, we will look at the history of used_pairs to avoid duplicates.
        In each call, each individual may only be used in one pair.
        """

        # Find all pairs that could be used. Also ensure data contains no duplicates
        possible_pairs = list(itertools.combinations(set(individuals), r=2))
        # Keep track of which individuals were used this call.
        used_individuals = set()

        # Add randomness when sampling possible pairs
        for a, b in random.sample(possible_pairs, len(possible_pairs)):
            # Sort the pair to ensure [a, b] collides with [b, a]
            if a > b:
                a, b = b, a
            # Check both the individuals haven't been used in this cycle
            if a in used_individuals or b in used_individuals:
                continue
            # Check that the pair has not been seen before.
            if (a, b) in self.used_pairs:
                continue

            # Register pair and individuals before yielding
            self.used_pairs.add((a, b))
            used_individuals.add(a)
            used_individuals.add(b)
            yield a, b

例句用法

generator = PairGenerator()
individuals = [1, 2, 3, 4, 5, 6,  7,  8,  9, 10]
for i in range(4):
    pairs = list(generator.next_pairs(individuals))

    print(f"Iteration {i}:")
    print(f"  {individuals=}")
    print(f"  {pairs=}")
    print(f"  used_pairs={len(generator.used_pairs)}")

    individuals.append(individuals.pop(0) + 10)
Iteration 0:
  individuals=[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
  pairs=[(1, 10), (2, 4), (3, 9), (5, 6), (7, 8)]
  used_pairs=5
Iteration 1:
  individuals=[2, 3, 4, 5, 6, 7, 8, 9, 10, 11]
  pairs=[(3, 7), (2, 8), (5, 9), (6, 10), (4, 11)]
  used_pairs=10
Iteration 2:
  individuals=[3, 4, 5, 6, 7, 8, 9, 10, 11, 12]
  pairs=[(3, 11), (6, 12), (7, 9), (4, 8), (5, 10)]
  used_pairs=15
Iteration 3:
  individuals=[4, 5, 6, 7, 8, 9, 10, 11, 12, 13]
  pairs=[(7, 11), (4, 13), (8, 10), (6, 9), (5, 12)]
  used_pairs=20

对于您的主代码,我们可以为如何创建新生物做类似的事情。

class CreatureGenerator:
    def __init__(self):
        self.last_creature = 0

    def next_creature(self):
        self.last_creature += 1
        return self.last_creature
pair_gen = PairGenerator()
creature_gen = CreatureGenerator()

reproducing_prob = 0.1  # probability of reproduction
death_prob = 0.1  # probability of death
pop_size = 10  # starting population size

creatures = set(creature_gen.next_creature() for _ in range(pop_size))

day = 0
while creatures:
    day += 1

    print("\nDay:", day)
    print("Population:", len(creatures), list(creatures))

    dead_creatures = {
        creature for creature in creatures
        if random.uniform(0, 1) < death_prob
    }
    creatures -= dead_creatures

    creature_pairs = list(pair_gen.next_pairs(creatures))
    new_creatures = {
        creature_gen.next_creature() for _ in creature_pairs
        if random.uniform(0, 1) < reproducing_prob
    }
    creatures.update(new_creatures)

    print("Dead Creatures:", len(dead_creatures), list(dead_creatures))
    print("Creature pairs:", len(creature_pairs), list(creature_pairs))
    print("New creatures:", len(new_creatures), list(new_creatures))
Day: 1
Population: 10 [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
Dead Creatures: 1 [1]
Creature pairs: 4 [(2, 4), (3, 6), (5, 9), (7, 8)]
New creatures: 2 [11, 12]

Day: 2
Population: 11 [2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]
Dead Creatures: 1 [2]
Creature pairs: 5 [(4, 10), (5, 6), (3, 8), (11, 12), (7, 9)]
New creatures: 1 [13]

Day: 3
Population: 11 [3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13]
Dead Creatures: 1 [13]
Creature pairs: 5 [(4, 7), (6, 11), (5, 10), (8, 9), (3, 12)]
New creatures: 1 [14]

Day: 4
Population: 11 [3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 14]
Dead Creatures: 2 [9, 12]
Creature pairs: 4 [(4, 14), (10, 11), (6, 8), (5, 7)]
New creatures: 0 []

Day: 5
Population: 9 [3, 4, 5, 6, 7, 8, 10, 11, 14]
Dead Creatures: 1 [11]
Creature pairs: 4 [(4, 6), (3, 7), (10, 14), (5, 8)]
New creatures: 0 []

Day: 6
Population: 8 [3, 4, 5, 6, 7, 8, 10, 14]
Dead Creatures: 0 []
Creature pairs: 3 [(8, 10), (6, 7), (3, 5)]
New creatures: 0 []

Day: 7
Population: 8 [3, 4, 5, 6, 7, 8, 10, 14]
Dead Creatures: 1 [4]
Creature pairs: 2 [(5, 14), (3, 10)]
New creatures: 0 []

Day: 8
Population: 7 [3, 5, 6, 7, 8, 10, 14]
Dead Creatures: 1 [7]
Creature pairs: 1 [(6, 14)]
New creatures: 0 []

Day: 9
Population: 6 [3, 5, 6, 8, 10, 14]
Dead Creatures: 1 [6]
Creature pairs: 1 [(3, 14)]
New creatures: 0 []

Day: 10
Population: 5 [3, 5, 8, 10, 14]
Dead Creatures: 0 []
Creature pairs: 1 [(8, 14)]
New creatures: 1 [15]

Day: 11
Population: 6 [3, 5, 8, 10, 14, 15]
Dead Creatures: 0 []
Creature pairs: 1 [(8, 15)]
New creatures: 0 []

Day: 12
Population: 6 [3, 5, 8, 10, 14, 15]
Dead Creatures: 3 [10, 14, 15]
Creature pairs: 0 []
New creatures: 0 []

Day: 13
Population: 3 [3, 5, 8]
Dead Creatures: 0 []
Creature pairs: 0 []
New creatures: 0 []

Day: 14
Population: 3 [3, 5, 8]
Dead Creatures: 0 []
Creature pairs: 0 []
New creatures: 0 []

Day: 15
Population: 3 [3, 5, 8]
Dead Creatures: 0 []
Creature pairs: 0 []
New creatures: 0 []

Day: 16
Population: 3 [3, 5, 8]
Dead Creatures: 1 [8]
Creature pairs: 0 []
New creatures: 0 []

Day: 17
Population: 2 [3, 5]
Dead Creatures: 0 []
Creature pairs: 0 []
New creatures: 0 []

Day: 18
Population: 2 [3, 5]
Dead Creatures: 0 []
Creature pairs: 0 []
New creatures: 0 []

Day: 19
Population: 2 [3, 5]
Dead Creatures: 0 []
Creature pairs: 0 []
New creatures: 0 []

Day: 20
Population: 2 [3, 5]
Dead Creatures: 0 []
Creature pairs: 0 []
New creatures: 0 []

Day: 21
Population: 2 [3, 5]
Dead Creatures: 0 []
Creature pairs: 0 []
New creatures: 0 []

Day: 22
Population: 2 [3, 5]
Dead Creatures: 0 []
Creature pairs: 0 []
New creatures: 0 []

Day: 23
Population: 2 [3, 5]
Dead Creatures: 0 []
Creature pairs: 0 []
New creatures: 0 []

Day: 24
Population: 2 [3, 5]
Dead Creatures: 0 []
Creature pairs: 0 []
New creatures: 0 []

Day: 25
Population: 2 [3, 5]
Dead Creatures: 1 [3]
Creature pairs: 0 []
New creatures: 0 []

Day: 26
Population: 1 [5]
Dead Creatures: 0 []
Creature pairs: 0 []
New creatures: 0 []

Day: 27
Population: 1 [5]
Dead Creatures: 0 []
Creature pairs: 0 []
New creatures: 0 []

Day: 28
Population: 1 [5]
Dead Creatures: 1 [5]
Creature pairs: 0 []
New creatures: 0 []
 类似资料:
  • 问题内容: 假设我有一个清单,例如: 在遍历此列表时,我想在列表末尾添加一个元素。但是我不想遍历新添加的元素,也就是我想遍历列表的初始大小。 有人可以建议我该怎么做吗? 问题答案: 您不能为此使用foreach语句。foreach在内部使用迭代器: 此类的迭代器和listIterator方法返回的迭代器是快速失败的:如果在创建迭代器之后的任何时间以任何方式对列表进行结构修改,则除了通过迭代器自己的

  • 我有一个名为计算的方法,它需要太长时间才能完成。所以我决定将我的信息列表对象部分发送到这个方法。我如何遍历每n个元素?

  • 问题内容: 我正在对JRE 进行迭代,该JRE 强制执行快速失败迭代器概念,因此如果在迭代时修改了,则会抛出a ,而不是使用method。但是,如果对象满足条件,则需要删除该对象的“逻辑伙伴”。从而阻止伙伴也被处理。我怎样才能做到这一点?也许为此使用更好的收集类型? 例。 谢谢。 问题答案: 您要从列表中删除项目,然后继续在同一列表中进行迭代。您是否可以实施两步解决方案,即在步骤1中将要删除的项目

  • 更新:这与运行10个不同初始随机值的独立模型是不同的。我希望更新发生在单个模型运行中,该模型本身在函数中有10次迭代。 希望你能帮忙。

  • 如何才能做到这一点呢? 谢谢大家。

  • 我在中有一个带有几个元素的,我正在做的是迭代并显示Array中与null不同的所有元素。 这是: 我的问题:是否可以在一行中迭代null以外的元素?