Is there an easy way to map elements of a list to each other?

Viewed 93

I am using python. Basically I have a large list with each value having a triple index: (i, j, t):

Y_1,2,1
Y_1,3,1

and so on.

What I want to do is extract specifically the values: Y_i,j,t and Y_j,i,t but I am having some difficulty.

So for example, I would want to be able to extract: Y_1,2,1 and Y_2,1,1. Y_1,3,4 and Y_3,1,4...

To populate my data I use:

N = 6
T = 2 * N - 2
list_ijt = []
    
for t in range(1, T + 1):
    for i in range(1, N + 1):
        for j in range(1, N + 1):
            # Avoid making Y_i,j=i,t index
            if j == i:
                continue
            element = "Y" + str(i) + ',' + str(j) + ',' + str(t)
            list_ijt.append(element)

Is there some way to do this for a general case n? Would it be easier done with a dictionary? I have tried and tried to come up with some algorithm or equation, like

for n in range(len(list_ijt)):
     match_index = 4 * (n + 1) + (n + 1) 
     print(list_ijt[n], list_ijt[match_index])

But to no avail, and with no clue how this would be generalized for any n (the above example was for n = 6).

Example list:

print(list_ijt)
['Y1,2,1', 'Y1,3,1', 'Y1,4,1', 'Y1,5,1', 'Y1,6,1', 'Y2,1,1', 'Y2,3,1', 'Y2,4,1', 'Y2,5,1', 'Y2,6,1', 'Y3,1,1', 'Y3,2,1', 'Y3,4,1', 'Y3,5,1', 'Y3,6,1', 'Y4,1,1', 'Y4,2,1', 'Y4,3,1', 'Y4,5,1', 'Y4,6,1', 'Y5,1,1', 'Y5,2,1', 'Y5,3,1', 'Y5,4,1', 'Y5,6,1', 'Y6,1,1', 'Y6,2,1', 'Y6,3,1', 'Y6,4,1', 'Y6,5,1', 'Y1,2,2', 'Y1,3,2', 'Y1,4,2', 'Y1,5,2', 'Y1,6,2', 'Y2,1,2', 'Y2,3,2', 'Y2,4,2', 'Y2,5,2', 'Y2,6,2', 'Y3,1,2', 'Y3,2,2', 'Y3,4,2', 'Y3,5,2', 'Y3,6,2', 'Y4,1,2', 'Y4,2,2', 'Y4,3,2', 'Y4,5,2', 'Y4,6,2', 'Y5,1,2', 'Y5,2,2', 'Y5,3,2', 'Y5,4,2', 'Y5,6,2', 'Y6,1,2', 'Y6,2,2', 'Y6,3,2', 'Y6,4,2', 'Y6,5,2', 'Y1,2,3', 'Y1,3,3', 'Y1,4,3', 'Y1,5,3', 'Y1,6,3', 'Y2,1,3', 'Y2,3,3', 'Y2,4,3', 'Y2,5,3', 'Y2,6,3', 'Y3,1,3', 'Y3,2,3', 'Y3,4,3', 'Y3,5,3', 'Y3,6,3', 'Y4,1,3', 'Y4,2,3', 'Y4,3,3', 'Y4,5,3', 'Y4,6,3', 'Y5,1,3', 'Y5,2,3', 'Y5,3,3', 'Y5,4,3', 'Y5,6,3', 'Y6,1,3', 'Y6,2,3', 'Y6,3,3', 'Y6,4,3', 'Y6,5,3', 'Y1,2,4', 'Y1,3,4', 'Y1,4,4', 'Y1,5,4', 'Y1,6,4', 'Y2,1,4', 'Y2,3,4', 'Y2,4,4', 'Y2,5,4', 'Y2,6,4', 'Y3,1,4', 'Y3,2,4', 'Y3,4,4', 'Y3,5,4', 'Y3,6,4', 'Y4,1,4', 'Y4,2,4', 'Y4,3,4', 'Y4,5,4', 'Y4,6,4', 'Y5,1,4', 'Y5,2,4', 'Y5,3,4', 'Y5,4,4', 'Y5,6,4', 'Y6,1,4', 'Y6,2,4', 'Y6,3,4', 'Y6,4,4', 'Y6,5,4', 'Y1,2,5', 'Y1,3,5', 'Y1,4,5', 'Y1,5,5', 'Y1,6,5', 'Y2,1,5', 'Y2,3,5', 'Y2,4,5', 'Y2,5,5', 'Y2,6,5', 'Y3,1,5', 'Y3,2,5', 'Y3,4,5', 'Y3,5,5', 'Y3,6,5', 'Y4,1,5', 'Y4,2,5', 'Y4,3,5', 'Y4,5,5', 'Y4,6,5', 'Y5,1,5', 'Y5,2,5', 'Y5,3,5', 'Y5,4,5', 'Y5,6,5', 'Y6,1,5', 'Y6,2,5', 'Y6,3,5', 'Y6,4,5', 'Y6,5,5', 'Y1,2,6', 'Y1,3,6', 'Y1,4,6', 'Y1,5,6', 'Y1,6,6', 'Y2,1,6', 'Y2,3,6', 'Y2,4,6', 'Y2,5,6', 'Y2,6,6', 'Y3,1,6', 'Y3,2,6', 'Y3,4,6', 'Y3,5,6', 'Y3,6,6', 'Y4,1,6', 'Y4,2,6', 'Y4,3,6', 'Y4,5,6', 'Y4,6,6', 'Y5,1,6', 'Y5,2,6', 'Y5,3,6', 'Y5,4,6', 'Y5,6,6', 'Y6,1,6', 'Y6,2,6', 'Y6,3,6', 'Y6,4,6', 'Y6,5,6', 'Y1,2,7', 'Y1,3,7', 'Y1,4,7', 'Y1,5,7', 'Y1,6,7', 'Y2,1,7', 'Y2,3,7', 'Y2,4,7', 'Y2,5,7', 'Y2,6,7', 'Y3,1,7', 'Y3,2,7', 'Y3,4,7', 'Y3,5,7', 'Y3,6,7', 'Y4,1,7', 'Y4,2,7', 'Y4,3,7', 'Y4,5,7', 'Y4,6,7', 'Y5,1,7', 'Y5,2,7', 'Y5,3,7', 'Y5,4,7', 'Y5,6,7', 'Y6,1,7', 'Y6,2,7', 'Y6,3,7', 'Y6,4,7', 'Y6,5,7', 'Y1,2,8', 'Y1,3,8', 'Y1,4,8', 'Y1,5,8', 'Y1,6,8', 'Y2,1,8', 'Y2,3,8', 'Y2,4,8', 'Y2,5,8', 'Y2,6,8', 'Y3,1,8', 'Y3,2,8', 'Y3,4,8', 'Y3,5,8', 'Y3,6,8', 'Y4,1,8', 'Y4,2,8', 'Y4,3,8', 'Y4,5,8', 'Y4,6,8', 'Y5,1,8', 'Y5,2,8', 'Y5,3,8', 'Y5,4,8', 'Y5,6,8', 'Y6,1,8', 'Y6,2,8', 'Y6,3,8', 'Y6,4,8', 'Y6,5,8', 'Y1,2,9', 'Y1,3,9', 'Y1,4,9', 'Y1,5,9', 'Y1,6,9', 'Y2,1,9', 'Y2,3,9', 'Y2,4,9', 'Y2,5,9', 'Y2,6,9', 'Y3,1,9', 'Y3,2,9', 'Y3,4,9', 'Y3,5,9', 'Y3,6,9', 'Y4,1,9', 'Y4,2,9', 'Y4,3,9', 'Y4,5,9', 'Y4,6,9', 'Y5,1,9', 'Y5,2,9', 'Y5,3,9', 'Y5,4,9', 'Y5,6,9', 'Y6,1,9', 'Y6,2,9', 'Y6,3,9', 'Y6,4,9', 'Y6,5,9', 'Y1,2,10', 'Y1,3,10', 'Y1,4,10', 'Y1,5,10', 'Y1,6,10', 'Y2,1,10', 'Y2,3,10', 'Y2,4,10', 'Y2,5,10', 'Y2,6,10', 'Y3,1,10', 'Y3,2,10', 'Y3,4,10', 'Y3,5,10', 'Y3,6,10', 'Y4,1,10', 'Y4,2,10', 'Y4,3,10', 'Y4,5,10', 'Y4,6,10', 'Y5,1,10', 'Y5,2,10', 'Y5,3,10', 'Y5,4,10', 'Y5,6,10', 'Y6,1,10', 'Y6,2,10', 'Y6,3,10', 'Y6,4,10', 'Y6,5,10']

Tried:

string = '\n'.join(list_ijt)
for t in range(T):
    for i in range(n):
        for j in range(i, n):
            s = get(i, j, t, string)
            if s:
                list_ijt.append(s)
2 Answers

Use

def get(i, j, t, string):
    def _get(i, j):
        pat = f'Y{i},{j},{t}'
        ind = string.find(pat)
        if ind >=0:
            return string[ind:ind+len(pat)]
    a, b = _get(i, j), _get(j, i)
    if a and b:
        return a, b
    
n = 3
T = 2*n-2
list_ijt = []

string = '\n'.join(your_list)
for t in range(T):
    for i in range(n):
        for j in range(i, n):
            if s := get(i, j, t, string):
                list_ijt.append(s)

print(list_ijt)
[('Y1,2,1', 'Y2,1,1'), ('Y1,2,2', 'Y2,1,2'), ('Y1,2,3', 'Y2,1,3')]

If your data is exactly as shown (no missing elements or anything like that), you can analyze the placement of elements pretty easily.

There are a total of T blocks of N * (N - 1) elements. Each block consists of N segments of N - 1 elements each. Each segment has a constant value of i. The first i - 1 elements are for j < i and the remainder for j > i.

So for a given choice of i, j, t, the index in the list is

(t - 1) * N * (N - 1) + (i - 1) * (N - 1) + j - (j > i) - 1

The expression (j > i) evaluates to a bool, which is an integer that's 0 or 1.

That means that the index for j, i, t is given by

(t - 1) * N * (N - 1) + (j - 1) * (N - 1) + i - (i > j) - 1

So if you have an index in the list, k, you can break it down into components and apply the second formula. The components are

t = (k // (N * (N - 1))) + 1
i = (k % (N * (N - 1))) // (N - 1) + 1
j = k % (N - 1) + 1
j += (j >= i)

So you can compute a match index for any k totally deterministically with arithmetic and boolean operations. You don't need loops or dictionaries in this particular case.

You can write your final loop as something like this:

for k in range(len(list_ijt)):
    t = (k // (N * (N - 1))) + 1
    i = (k % (N * (N - 1))) // (N - 1) + 1
    j = k % (N - 1) + 1
    j += (j >= i)
    match_index = (t - 1) * N * (N - 1) + (j - 1) * (N - 1) + i - (i > j) - 1
    print(list_ijt[k], '->', list_ijt[match_index])
Related