0

So the problem is essentially this: I have a list of tuples made up of n ints that have to be eliminated if they dont fit certain criteria. This criterion boils down to that each element of the tuple must be equal to or less than the corresponding int of another list (lets call this list f) in the exact position.

So, an example:

Assuming I have a list of tuples called wk, made up of tuples of ints of length 3, and a list f composed of 3 ints. Like so:

wk = [(1,3,8),(8,9,1),(1,1,1)]
f = [2,5,8]
=== After applying the function ===
wk_result = [(1,3,8),(1,1,1)]

The rationale would be that when looking at the first tuple of wk ((1,3,8)), the first element of it is smaller than the first element of f. The second element of wk also complies with the rule, and the same applies for the third. This does not apply for the second tuple tho given that the first and second element (8 and 9) are bigger than the first and second elements of f (2 and 5).

Here's the code I have:

for i,z in enumerate(wk):
    for j,k in enumerate(z):
        if k <= f[j]:
            pass
        else:
            del wk[i]

When I run this it is not eliminating the tuples from wk. What could I be doing wrong?

EDIT

One of the answers provided by user @James actually made it a whole lot simpler to do what I need to do:

[t for t in wk if t<=tuple(f)]
#returns:
[(1, 3, 8), (1, 1, 1)]

The thing is in my particular case it is not getting the job done, so I assume it might have to do with the previous steps of the process which I will post below:

max_i = max(f)
siz = len(f)
flist = [i for i in range(1,max_i +1)]
def cartesian_power(seq, p):
    if p == 0:
        return [()]
    else:
        result = []
        for x1 in seq:
            for x2 in cartesian_power(seq, p - 1):
                result.append((x1,) + x2)
        return result
wk = cartesian_power(flist, siz)
wk = [i for i in wk if i <= tuple(f) and max(i) == max_i]

What is happening is the following: I cannot use the itertools library to do permutations, that is why I am using a function that gets the job done. Once I produce a list of tuples (wk) with all possible permutations, I filter this list using two parameters: the one that brought me here originally and another one not relevant for the discussion.

Ill show an example of the results with numbers, given f = [2,5,8]:

[(1, 1, 8), (1, 2, 8), (1, 3, 8), (1, 4, 8), (1, 5, 8), (1, 6, 8), (1, 7, 8), (1, 8, 1), (1, 8, 2), (1, 8, 3), (1, 8, 4), (1, 8, 5), (1, 8, 6), (1, 8, 7), (1, 8, 8), (2, 1, 8), (2, 2, 8), (2, 3, 8), (2, 4, 8), (2, 5, 8)]

As you can see, there are instances where the ints in the tuple are bigger than the corresponding position in the f list, like (1,6,8) where the second position of the tuple (6) is bigger than the number in the second position of f (5).

DSM
  • 291,791
  • 56
  • 521
  • 443
  • I don't know if this is your problem but - [Removing Item From List - during iteration - what's wrong with this idiom?](https://stackoverflow.com/q/2896752/2823755) – wwii Jan 21 '18 at 01:07
  • you want to compare first , second or only first element in tuple? –  Jan 21 '18 at 14:52
  • @netplay I'm actually trying to compare all elements of the tuple with all the elements of list f. – Frank Pinto Jan 21 '18 at 19:57
  • @FrankPinto that's what i did in my solution. –  Jan 22 '18 at 13:58

3 Answers3

2

You can do this with a list comprehension. It iterates over the list of tuples and checks that all of the elements of the tuple are less than or equal to the corresponding elements in f. You can compare tuples directly for element-wise inequality

[t for t in wk if all(x<=y for x,y in zip(t,f)]
# returns:
[(1, 3, 8), (1, 1, 1)]
James
  • 25,833
  • 3
  • 34
  • 55
  • This was actually pretty helpful, thank you. The thing is it's not working for the particular case I have at hand and I'm not sure why. I'm going to edit the question out to show this, hopefully, somebody can catch the mistakes. – Frank Pinto Jan 21 '18 at 14:10
  • 1
    `t <= tuple(f)` does _not_ check whether all the elements of the tuple are less than or equal to the corresponding elements in f. (1,2,3) < (1,3,2) because 1 == 1 and 2 < 3; it doesn't even get to the point of checking whether 3 < 2. – DSM Jan 21 '18 at 14:52
2

You can use list comprehension with a (short-circuiting) predicate over each tuple zipped with the list f.

wk = [(1, 3, 8), (8, 9, 1), (1, 1, 1), (1, 9, 1)]
f = [2, 5, 8] # In this contrived example, f could preferably be a 3-tuple as well.

filtered = [t for t in wk if all(a <= b for (a, b) in zip(t, f))]
print(filtered) # [(1, 3, 8), (1, 1, 1)]

Here, all() has been used to specify a predicate that all tuple members must be less or equal to the corresponding element in the list f; all() will short-circuit its testing of a tuple as soon as one of its members does not pass the tuple member/list member <= sub-predicate.

Note that I added a (1, 9, 1) tuple for an example where the first tuple element passes the sub-predicate (<= corresponding element in f) whereas the 2nd tuple element does not (9 > 5).

dfrib
  • 56,823
  • 7
  • 97
  • 157
  • For some reason when I run this solution on my problem (as in the list of tuples provided by the function presented above) it does not filter the tuples that dont comply with the criterion. – Frank Pinto Jan 21 '18 at 20:05
  • 1
    Well, for some reason, I broke down the the list comprehension into its unpythonic form and it worked. Thanks. – Frank Pinto Jan 21 '18 at 20:19
0

Here is without loop solution which will compare each element in tuple :

wk_1 = [(1,3,8),(8,9,1),(1,1,1)]
f = [2,5,8]

final_input=[]



def comparison(wk, target):
    if not wk:
        return 0
    else:
        data=wk[0]
        if data[0]<=target[0] and data[1]<=target[1] and data[2]<=target[2]:
            final_input.append(data)
        comparison(wk[1:],target)


comparison(wk_1,f)

print(final_input)

output:

[(1, 3, 8), (1, 1, 1)]

P.S : since i don't know you want less and equal or only less condition so modify it according to your need.