Create pairs of items with similarity constraints I want to create N unordered pairs of items (no repeat pairs, no pairs with repeated items), where each item is only used twice. For example, given the minimal amount of integers greater than 0, one possible set of 4 items would be:

[(0, 1), (0, 2), (3, 1), (3, 2)]


Another valid example would be:

[(0, 1), (1, 2), (2, 3), (3, 0)]


This would be invalid due to repeated pair:

[(0, 1), (0, 1), (2, 3), (3, 1)]


This would be invalid due to the item 0 being used three times:

[(0, 1), (0, 2), (0, 3), (3, 2)]


Also, to be clear the pair (0, 0) is invalid because it is a pair with a repeated item.

My current code for accomplishing this is clumsy and only works multiples of 4. For now, let's assume the code only needs to work for multiples of 4. How could I do this with a better iterator?

num_set = range(4)
res = []
for n1, n2, n3, n4 in zip(num_set[::4], num_set[3::4], num_set[1::4], num_set[2::4]):
    res.append((n1, n3))
    res.append((n1, n4))
    res.append((n2, n3))
    res.append((n2, n4))

print(res)


I feel like I should be able to use itertools.combinations(range(4), 2) and some filtering to accomplish this, but I'm not sure how.
The simplest answer I could come up with exploits the structure of the problem and gives a deterministic answer, but since I didn't specify the answer had to be random, I think it's valid.

Basically, the pairs [(0, 1), (1, 2), (2, 3), (3, 0)] are equivalent to some creative slicing of the list d_list = [0, 0, 1, 1, 2, 2, 3, 3]. I couldn't figure out how to slice it properly, so instead I used a hacky re-arrangement of d_list.append(d_list.pop(0)). This gives d_list = [0, 1, 1, 2, 2, 3, 3, 0] which I can then slice into pairs trivially.

Complete code below:

n_items = 5

nums = list(range(n_items))

d_list = []
for nn in nums:
    d_list.append(nn)
    d_list.append(nn)

d_list.append(d_list.pop(0))

pairs = []
for i1, i2 in zip(d_list[::2], d_list[1::2]):
    pairs.append((i1, i2))


It's definitely not the prettiest code, but it works.