4

I have a file with data that I want to separate into various lists depending on the value in the first column. I know exactly what the possible values within the first column are, but they are not in any nice mathematical progression. Is there a shorter way to write the following code?

x0=[]
y0=[]
x2=[]
y2=[]
x16=[]
y16=[]
# etc.

for line in file:
    words=line.split()
    if words[0] == '0':
        x0.append(words[1])
        y0.append(words[2])
    elif words[0] == '2':
        x2.append(words[1])
        y2.append(words[2])
    elif words[0] == '16':
        x16.append(words[1])
        y16.append(words[2])
    # etc.

My thought process is below, but the strings (x and y) that I define are obviously strings and don't refer back to the lists that I want them to refer to.

x0=[]
y0=[]
x2=[]
y2=[]
x16=[]
y16=[]
# etc

for line in file:
    words=line.split()
    x='x'+words[0]
    y='y'+words[0]
    x.append(words[1])
    y.append(words[2])

Update: I realize it is possible to do this with a dictionary, where my value would be a list of lists, but mainly I'm curious if there is a pythonic way to code this that follows my train of thought as outlined above.

5 Answers 5

6

Use a defaultdict instead of a bunch of individual values.

from collections import defaultdict
extracted_values = defaultdict(list)
for line in file:
    words = line.split()
    extracted_values['x' + words[0]].append(words[1])
    extracted_values['y' + words[0]].append(words[2])

Then you'd just access your values by dictionary key instead of variable name.

extracted_values['x0']
extracted_values['y1']
Sign up to request clarification or add additional context in comments.

Comments

5

I suggest that you turn

x0=[]
x2=[]
x16=[]

into a single dictionary:

x={'0':[], '2':[], '16':[]}

You can then reference the individual lists as x['0'], x['2'] etc.

In particular, you'll be able to rewrite the for loop like so:

for line in file:
    words = line.split()
    x[words[0]].append(words[1])
    y[words[0]].append(words[2])

1 Comment

Thanks! This is what I ended up doing. I had the realization that this would be the easiest way about 20 seconds after I posted my question (happens to everyone), but by that point I was just curious to see how else it would be possible. Always trying to expand my Python knowledge.
0

Some people will shout, but I still don't understand why they frown upon the use of globals()

for line in file:
    words=line.split()
    zx,zy = 'x%d' % words[0], 'y%d' % words[0]
    if zx not in globals():
        globals()[zx] = []
        globals()[zy] = []
    globals()[zx].append(words[1])
    globals()[zy].append(words[2])

5 Comments

globals is a giant, uncontrolled namespace. It's not good to use if you ever intend to play nice with any other code anywhere. It breaks encapsulation, it make code nearly impossible to follow, and unless you are very careful about cleaning it up yourself, it brings all the problems of memory leaks and null pointers in to Python for no gain. There's really nothing good about using globals.
@sr2222's already hit the encapsulation issue (the equivalent trick with locals() won't work in a function, so we've got to use globals()), so how about the practical one: now what? You've got x0, x2, and x16 in the global namespace. What can you do with them? You can either refer to them explicitly (meaning any similar ops on the lists will be written in triplicate), or you have to store references to them in a list/tuple or a dict anyhow to loop over them, in which case why didn't we just do that in the first place?
It is controlled by the interpreter, or I don't know which other entity, I'm not very skilled in Python - What's the difference between x2 = [ ] and globals()['x2'] = [ ] ? - " if you ever intend to play nice with any other code anywhere" Give example, please. - What does mean break encapsulation. Give a link to some tuorial or blog that explain this, please. - Impossible to follow = to read ??? I don't have this feeling. - I would like to know how memory leaks are generated by use of globals() - Null pointer ??
(1) x2 = [] could declare a local variable in a function; obviously modifying globals() can't. (2) What if another function used the same trick? Your x2 could shadow someone else's x2. Not playing nice, which is (3) breaking encapsulation -- you can't isolate your behaviour ("put them in a capsule"). (4) As for impossible to follow -- it's hard to come up with a good example offhand, because no one does this in real code. But imagine that every function used the same variable names, as before, or (as I asked earlier) imagine what you'd do next, after this.
It's impossible to follow in any code outside of toy examples because any code, any where, without any notification, can just as easily add, modify, or delete any value from globals as your code can. If you set a global in module A and then use it in module B, the only way for someone working with the code later to track down where the value is being set is to step through the code line by line. As to encapsulation, read up on object oriented design.
0

You could use the globals() dictionary, thus:

x0=[]
y0=[]
x2=[]
y2=[]
x16=[]
y16=[]
# etc

for line in file:
    words=line.split()
    x=globals()['x'+words[0]]
    y=globals()['y'+words[0]]
    x.append(words[1])
    y.append(words[2])

3 Comments

Technically true, but that's just a way to recover from a self-inflicted wound. Keep data out of variable names, as the man said.
You could do that. Python gives you lots of ways to make your code very difficult to read. Of course could is not should...
The OP asked if could, not if he should.
0

Yeah, you should use a dictionary. But to answer your question, you could use locals(), or, more flexibly, assemble the command you want and execute it with eval. E.g., if your data is all numeric:

words = line.split()
eval("x%s.append(%s)" % (words[0], words[1]))
eval("y%s.append(%s)" % (words[0], words[2]))

Note that line.split() gives you strings, even if they consist only of digits. Hence %s, not %d.

But anyway, don't do it. Use a dict.

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.