4

I got two list of lists

l1 = [[1,2,3],[4,5,6],[7,8,9]]
l2 = [['a','b',4],['c','d',1],['e','f',12],['i','j',18]]

I would like to iterate over l1 and check if l1[0] matches with any l2[2], In this case the output should be [1, l1[0],l2[0]] otherwise output is [0, l1[0], l2[0]]. Output should be a single nested list(or list of tuples) with result for each element of l1. Both lists can have different sizes.

I tried solving this with for-loop like:

output = list()
for i in l1:
   matched = 0
   for j in l2:
       if j[2] == i[0]:
          output.append([1,i[0], j[0]])
          matched = 1
    if matched == 0:
       output.append([0,i[0]])

This give correct output

[[1, 1, 'c'], [1, 4, 'a'], [0, 7]]

However I am looking for a more compact solution. Is it possible to solve this with list comprehension of something similar which can reduce number of lines involved?

I tried a nested list comprehension but couldn't make it work

out = [[(1,i[0],k[0]) if(k[2] == i[0]) else (0,i[0],k[0]) for k in l2] for i in l1]
print(out)
[[(0, 1, 'a'), (1, 1, 'c'), (0, 1, 'e'), (0, 1, 'i')], [(1, 4, 'a'), (0, 4, 'c'), (0, 4, 'e'), (0, 4, 'i')], [(0, 7, 'a'), (0, 7, 'c'), (0, 7, 'e'), (0, 7, 'i')]]
9
  • 1
    Did you consider using a dict for finding what you search for? Commented Dec 21, 2017 at 15:38
  • You can do this in one line, but it looks really bad. Commented Dec 21, 2017 at 15:39
  • @cᴏʟᴅsᴘᴇᴇᴅ how bad? Commented Dec 21, 2017 at 15:40
  • @Alfe sorry not sure how to use dict here Commented Dec 21, 2017 at 15:40
  • [next(([1, x[0], y[0]] for y in l2 if x[0] == y[-1]), [0, x[0], l2[-1][0]]) for x in l1] Commented Dec 21, 2017 at 15:40

2 Answers 2

3

it seems that you're not using all your elements. However, I'd build a dict out of l2 for quick lookup & concision (one-liner would be probably possible, but at the expense of readability & performance)

I'd make that follow with a list comprehension including a ternary to issue 2 or 3 elements depending if the item is found (so no need for a fancy int(if a in l2d) since we can issue 0 or 1 directly). Like this:

l1 = [[1,2,3],[4,5,6],[7,8,9]]
l2 = [['a','b',4],['c','d',1],['e','f',12],['i','j',18]]

l2d = {v[2]:v[0] for v in l2}  # not using v[1]

result = [[1,a,l2d[a]] if a in l2d else [0,a] for a,_,_ in l1]  # using only first element of each l1 triplet...

result:

[[1, 1, 'c'], [1, 4, 'a'], [0, 7]]

(note that carrying other unused items isn't really helping to understand the issue)

Sign up to request clarification or add additional context in comments.

1 Comment

I have updated my question. In case of no match i[0] will be the output
1

Better build a dictionary to speed up searching.

d = { c: a for [a,b,c] in l2 }

Now you can use this:

[[int(a in d), a] + ([d[a]] if a in d else [])
 for a,b,c in l1]

This returns

[[1, 1, 'c'], [1, 4, 'a'], [0, 7]]

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.