在列表中查找 `n` 个不同的元素,有重复项,== 可以,=== 不行

Find `n` distinct elements in list with duplicates, == is okay, === is not

我正在尝试实施差异进化优化算法,我需要一种从列表中获取不同实体的方法。它们可以是相同的值,但不能是相同的实体。

solutions = [[random.uniform(0, 1) for _ in range(30)] \
  for _ in range(100)]
for base_agent in solutions:
  agents = []
  while len(agents) < 3:
    p = solutions[random.randint(0, len(solutions))]
    if p in agents or p is base_agent:
      continue
    else:
      agents.add(p)
  if base_agent in agents \
    or agents[0] is agents[1] \
    or agents[1] is agents[2] \
    or agents[2] is agents[0]:
      print("Bad execution")
      exit(1)
print("Correct execution")

这是我所追求的(非工作)总体思路。

我希望 base_agent 不在 agents 中,并且我希望 agents 不包含重复条目。条目可以是相同的值(例如,它们可以 ==),但它们不能是相同的实体(例如,它们不能 ===)。 agents 在此 while 循环结束时应包含 3 个元素。

random.sample 可以给我一个列表中的随机样本,但它仍然可能包括 base_agent.

有什么想法吗?

is 是“不同元素”的 python 运算符。虽然,不完全像 JavaScript ===is 所做的是比较内存地址。

最简单的代码是只使用 random.sample,排除您要避免的单个元素。当然,它涉及到除 base_element 之外的所有元素的切片,但是当 n 仅为 30:

时,O(n²) 工作并不是什么大问题
import random

for i, base_agent in enumerate(solutions):
    agents = random.sample(solutions[:i] + solutions[i+1:], 3)
    # Do stuff with base_agent which is distinct from all elements of agents

如果你真的讨厌切片或根本不使用索引值,你可以用 itertools.combinations 做一些俗气的修改,让它为你生成所有与当前 base_agent 不匹配的值:

import random
from itertools import combinations

for base_agent, other_agents in zip(solutions, combinations(reversed(solutions), len(solutions) - 1)):
    agents = random.sample(other_agents, 3)

组合“除了一个元素之外的所有元素”,以相反的顺序使用 solutions 意味着 combinations 的每个输出都是所有元素,但在 [=18= 的每次迭代中得到的元素除外], 所以不需要切片。