0

I have two lists structured somehow like this:

A= [[1,27],[2,27],[3,27],[4,28],[5,29]]
B= [[6,30],[7,31],[8,31]]

and i have a file that has numbers:

1     5
2     3
3     1
4     2
5     5
6....

i want a code that reads this file and maps it to the list. e.g if the file has 1, it should read A list and output 27, if it has 6, it should read B and print 30, such that I get

27 29
27 27
27 27
28 27
29 29
30 31

The problem is, that my code gives index error, i read the file line by line and have an if condition that checks if the number i read from the file is less than the maximum number in list A, if so, it outputs the second character of that list and otherwise move on. The problem is, that instead of moving on to list B, my program still reads A and gives index error.

with open(filename) as myfile:
  for line in myfile.readlines():
     parts=line.split()
      if parts[0]< maxnumforA:
        print A[int(parts[0])-1]
      else:
        print B[int(parts[0]-1)
8
  • How do you get maxnumforA ? Commented Nov 23, 2016 at 15:49
  • 1
    parts[0] is a string, how are you comparing it to maxnumforA (or rather, what is maxnumforA?)? Commented Nov 23, 2016 at 15:49
  • 2
    Why not use a dictionary rather than a list? Is there a reason why you've split the list across two variables? Commented Nov 23, 2016 at 15:49
  • 1
    As an aside, you do not need to call file.readlines() to iterate over lines in a file. You can just write for line in file: Commented Nov 23, 2016 at 15:54
  • maxnumforA is 29, i define it earlier in my code. Yes, I need to split the data in two halves because it is required later. For use later in the code, I cannot combine the two lists Commented Nov 23, 2016 at 15:55

2 Answers 2

3

You should turn that lists into dictionaries. For example:

_A = dict(A)
_B = dict(B)

with open(filename) as myfile:
    for line in myfile:
        parts = line.split()
        for part in parts:
            part = int(part)
            if part in _A:
                print _A[part]
            elif part in _B:
                print _B[part]

If the action that will take place does not need to know if it comes from A or B, both can be turned into a single dictionary:

d = dict(A + B)  # Creating the dictionary

with open(filename) as myfile:
    for line in myfile:
        parts = line.split()
        for part in parts:
            part = int(part)
            if part in d:
                print d[part]

Creating the dictionary can be acomplished in many different ways, I will list some of them:

  • d = dict(A + B): First joins both lists into a single list (without modifying A or B) and then turns the result into a dictionary. It's the most clear way to do it.
  • d = {**dict(A), **dict(B)}: Turns both lists into two separates dictionaries (without mmodifying A or B), unpacks them and pack both of them into a single dictionary. Slighlty (and I mean really slightly) faster than the previous method and less clear. Proposed by @Nf4r
  • d = dict(A) & d.update(B): Turns the first list into a dictionary and updates that dictionary with the content of the second list. Fastest method, 1 line of code per list instead of 1 line for any list and no temporary objects generation so more efficient memory-wise.
Sign up to request clarification or add additional context in comments.

4 Comments

Thanks this helped. Simple and clear. solved the problem
@LilySharpton if you are going to do the same if it is located in A or B you could swap the code a bit to use a single dict as I suggested in a comment below, editing my answer to include this too
@Adirio check my answer to your statement below, because you are wrong.
@Nf4r I checked and your benchmark is not right, you are comparing your answer with an invented one. My answer is as fast as yours and is way more clear. If speed is a must dict updating is the fastest way to do it. Will include all the proposed solutions on the answer anyway.
0

As everyone stated before, dict would be much better. I don't know if the left-sided values in each lists are unique, but if yes, you could just go for:

d = {**dict(A), **dict(B)} # available in Python 3.x
with open(filename) as file: 
    for line in file.readlines():
        for num in line.split():
            if int(num) in d:
                print(d[int(num)])

3 Comments

Creating two dictionaries to unpack them to create a third one is a bad solution, you could have gone for d = dict(A+B)
Actualy the way I've done is is much faster than your way. By saing d = dict(A + B) you are creating extra list and then iterating over it. I've done a simple session, which you can check on: gist.github.com/anonymous/cedc9ce814edd1b8ec71395ceaf55e05
That gist is not right: you are comparing your solution d = {**dict(A), **dict(B)} with an invented solution d = {**dict(A + B)} that is actually unpacking and packing the dictionary for no benefit. My answer (d = dict(A+B)) takes more or less the same time yours does, you can check. If you want to be fast use dict updating: d = dict(A); d.update(B). The gist comparing your solution with both of the can be found here: gist.github.com/Adirio/4e566b7570ccdb044a5c25eec9fd3ccd

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.