PYTHON - creating multiple lists in a loop [duplicate] - python

This question already has answers here:
How can you dynamically create variables? [duplicate]
(8 answers)
Closed 7 years ago.
I'm trying to put together a programming project at my university, but I'm stuck. The "math" part I've got covered, but I need help with lists and loops in Python.
I'm working with graphs, let me show one example, to make it clearer:
3 node graph
As you can see, I have 3 nodes in it and 2 edges, nothing fancy. I need to compute the closest route between each pair of nodes, and I have that covered already. Now I need to put it either in n lists, n elements each, or in a n x n, so either:
a = [0, 1, 2]
b = [1, 0, 1]
c = [2, 1, 0]
or a table (or matrix?) like this:
table 3x3, where I only really need the part with the white background.
When I read data to work on, I put each node into a list, as a new element, so with these 3 steps I gradually get:
lw = []
lw = ['a']
lw = ['a','b']
lw = ['a','b','c']
Is there any way, to create empty lists out of elemnts of lw? I would really like to name them like dis_a, dis_b, dis_c etc. I tried to do it with a dictionary, but then I couldn't manipulate with those lists, like I usually do. And truth be told, I'd much prefer the solution using lists, as I already have a latter part of the program written for this.
EDIT:
Ok, so one of you asked for input/output to make my question clearer. Mmy input is:
lw = ['a','b','c']
my desired output is:
a = []
b = []
c = []
or something like that (lists that can be easly identified with the nodes, that I have listed in lw)
EDIT2:
Ok, so now I have a number of lists created like this (still sticking to the example):
dis['a']
dis['b']
dis['c']
I have a working command
path[X][Y]
which on input takes the names of the nodes (as in lw list ex. 'a'), and on input returns a list of
nodes on the shortest path from X to Y. What I need to be doing now, is to take the length of it with
len(path[X][Y])
And substract 1 from it (it's counting the "starting" point as well, so it's correcting it). Then I have
to put this number in a corresponding place in a list. I would like to do it in a loop, so it would
automatically append numbers to existing lists, so I would automatically get from
dis['a'] = []
dis['b'] = []
dis['c'] = []
to
dis['a'] = [0, 1, 2]
dis['b'] = [1, 0, 1]
dis['c'] = [2, 1, 0]
Don't worry, about it calculating the path twice (ex. from a to b and then from b to a), It doesn't have to be perfect ;) I tried to create such method, but I have no idea, how to store the results in said lists (or if I'm even correct). Here is my proposition:
def lo():
for i in range(0, len(lw)):
for j in range (0, len(lw)):
dis[i].append(path[lw[i]][lw[j]])

What couldn't you manipulate with a dictionary?
dis_a, dis_b, dis_c... could as well be dis['a'], dis['b'] and dis['c']...
You could do:
dis = {}
for elem in lw:
dis[elem] = []
# ...
Want to loop over all dis-es now?
for elem, val in dis.iteritems():
print elem # your a, b, or c
print val # your [] corresponding to a, b, or c
If you want to add elements, and find min and max (as requested in the comments):
Let's say initially dis['a'] gets [0, 1, 2]
and ...
dis['b'] = [1, 0, 1]
dis['c'] = [2, 1, 0]
and now you want to add a new item to all of the dis-es...
item = 5
for elem in dis:
dis[elem].append(item)
and now you want to find the max ...
for elem in dis:
print max(dis[elem])

If I'm correct you want to dynamically create variables.
Here is short answer, for more information checkout this post How can you dynamically create variables via a while loop? Actually there you can find different approaches like using a dict.
>>> lw = ['a', 'b', 'c']
>>> for l in lw:
exec("{prefix}{var}=[]".format(prefix="dis_", var=l))
>>> dis_a
[]
>>> dis_b.append('some')
>>> dis_b
['some']

Related

Python: Assaign values to variables using two lists [duplicate]

This question already has answers here:
Convert string to variable name in python [duplicate]
(3 answers)
Closed 7 years ago.
How can I assign values to variables by using two lists:
Numbers =[1,2,3,4,]
Element= ["ElementA","ElementB","ElementC","ElementD"]
for e, n in zip(Element, Numbers):
e+ ' = ' +n #this part is wrong
What i want is a result like this in the end:
print ElementA
>1
print ElementB
>2
print ElementC
>3
print ElementD
>4
So what im trying to do is to fill up variables created from one list (Element) with values from another list (Numbers) in a kind of loop style.
Does anyone know how to archive something like that?
It should also be possible to assign many values contained in a list/array to variables.
Do not do that.
You're already working with lists, so just create a list instead of hacking some hard-coded names. You could use a dictionary if you really wanted to use identifiers like A, B, etc., but you'd have a problem with more than 26 items, and you're just using it to make a sequence anyway. Integers are great for that, and of course we'll start at 0 because that's how it works.
>>> numbers = [1, 2, 3, 4]
>>> elements = [item for item in numbers]
>>> elements[0]
1
And at this point we can see that, for this example at least, you already had what you were looking for this whole time, in numbers.
>>> numbers = [1, 2, 3, 4]
>>> numbers[0]
1
Perfect.
You may use exec but this is generally the wrong way to go.
for e, n in zip(Element, Numbers):
exec(e + ' = ' + n)
You better should use a dictionnary:
my_dict = {}
for e, n in zip(Element, Numbers):
my_dict[e] = n
Even simpler:
my_dict = dict(zip(Element, Numbers))

Optimize search to find next matching value in a list

I have a program that goes through a list and for each objects finds the next instance that has a matching value. When it does it prints out the location of each objects. The program runs perfectly fine but the trouble I am running into is when I run it with a large volume of data (~6,000,000 objects in the list) it will take much too long. If anyone could provide insight into how I can make the process more efficient, I would greatly appreciate it.
def search(list):
original = list
matchedvalues = []
count = 0
for x in original:
targetValue = x.getValue()
count = count + 1
copy = original[count:]
for y in copy:
if (targetValue == y.getValue):
print (str(x.getLocation) + (,) + str(y.getLocation))
break
Perhaps you can make a dictionary that contains a list of indexes that correspond to each item, something like this:
values = [1,2,3,1,2,3,4]
from collections import defaultdict
def get_matches(x):
my_dict = defaultdict(list)
for ind, ele in enumerate(x):
my_dict[ele].append(ind)
return my_dict
Result:
>>> get_matches(values)
defaultdict(<type 'list'>, {1: [0, 3], 2: [1, 4], 3: [2, 5], 4: [6]})
Edit:
I added this part, in case it helps:
values = [1,1,1,1,2,2,3,4,5,3]
def get_next_item_ind(x, ind):
my_dict = get_matches(x)
indexes = my_dict[x[ind]]
temp_ind = indexes.index(ind)
if len(indexes) > temp_ind + 1:
return(indexes)[temp_ind + 1]
return None
Result:
>>> get_next_item_ind(values, 0)
1
>>> get_next_item_ind(values, 1)
2
>>> get_next_item_ind(values, 2)
3
>>> get_next_item_ind(values, 3)
>>> get_next_item_ind(values, 4)
5
>>> get_next_item_ind(values, 5)
>>> get_next_item_ind(values, 6)
9
>>> get_next_item_ind(values, 7)
>>> get_next_item_ind(values, 8)
There are a few ways you could increase the efficiency of this search by minimising additional memory use (particularly when your data is BIG).
you can operate directly on the list you are passing in, and don't need to make copies of it, in this way you won't need: original = list, or copy = original[count:]
you can use slices of the original list to test against, and enumerate(p) to iterate through these slices. You won't need the extra variable count and, enumerate(p) is efficient in Python
Re-implemented, this would become:
def search(p):
# iterate over p
for i, value in enumerate(p):
# if value occurs more than once, print locations
# do not re-test values that have already been tested (if value not in p[:i])
if value not in p[:i] and value in p[(i + 1):]:
print(e, ':', i, p[(i + 1):].index(e))
v = [1,2,3,1,2,3,4]
search(v)
1 : 0 2
2 : 1 2
3 : 2 2
Implementing it this way will only print out the values / locations where a value is repeated (which I think is what you intended in your original implementation).
Other considerations:
More than 2 occurrences of value: If the value repeats many times in the list, then you might want to implement a function to walk recursively through the list. As it is, the question doesn't address this - and it may be that it doesn't need to in your situation.
using a dictionary: I completely agree with Akavall above, dictionary's are a great way of looking up values in Python - especially if you need to lookup values again later in the program. This will work best if you construct a dictionary instead of a list when you originally create the list. But if you are only doing this once, it is going to cost you more time to construct the dictionary and query over it than simply iterating over the list as described above.
Hope this helps!

Making a list of lists in a For Loop

How do you make a list of lists within a for loop?
Here is what I have coded right now:
a = 0
xy=[[[],[]],[[],[]],[[],[]],[[],[]],[[],[]],[[],[]],[[],[]],[[],[]],[[],[]],[[],[]],[[],[]],[[],[]]]
for liness in range(len(NNCatelogue)):
a=0
for iii in range(len(NNCatelogue[liness])):
while a < len(catid):
if catid[a]==NNCatelogue[liness][iii]:
xyiii = (catid[a], a)
xy.append(xyiii)
a += 1
The output that I get is a lengthy list of pairs, as expected. It looks somewhat like the following:
[...,('C-18-1262', 30908),
('C-18-1264', 30910),
('C-18-1265', 30911),
('C-18-1267', 30913),
('C-18-1250', 30896),
('C-18-1254', 30900),...]
I would like to turn this list of pairs into a list of lists of pairs though. There are 1268 iterations, and the length of each list should be 12. (So 1268 lists with 12 elements in each of them). Any ideas for how to approach this when in a loop?
Something like this, perhaps. Note that I am using iteration over the lists directly to save a lot of unnecessary indexing.
xy = []
for line in NNCatelogue:
l = []
for c in line:
for a, ca in enumerate(catid):
if ca == c:
l.append((ca, a))
xy.append(l)
If you're using the inner loop just to search for the category index, as I suspect you are, a dictionary may be a useful addition to avoid the inner loop.
I have a few friendly suggestions right off the bat:
First of all, the a=0 at the very beginning is redundant. You do the
same thing twice with the a=0 inside of the first for loop.
Second, why are you declaring a huge framework of list elements for xy at
the top? You can always append() what you need as you go
along.
Finally, your while loop is just a simple for loop:
for n in range(len(catid)):
You can make a list of lists using list expansions like so:
list_of_lists = [[j for j in range(0, 3)] for _ in range(0, 3)]
Which outputs a 3x3 list:
[ [0, 1, 2],
[0, 1, 2],
[0, 1, 2]
]

Python unique list using set [duplicate]

This question already has answers here:
How do I remove duplicates from a list, while preserving order?
(31 answers)
Closed 8 months ago.
What I am trying to do is write a method that takes a list as an argument and uses a set to return a copy of the list where each element only occurs once, as well as having the elements in the new list occur in order of their first occurrence in the original list. I HAVE to use a set for this, however, I can't make it so that the output is in the right order while having a quick result.
If I put something like this:
def unique(a):
return list(set(a))
and passed a list with millions of elements, it would give me a result quickly, but it wouldn't be ordered.
So what I have right now is this:
def unique(a):
b = set(a)
c = {}
d = []
for i in b:
c[a.index(i)] = i
for i in c:
d.append(c[i])
return d
This gives me the result I want, but not fast enough. If I pass a list with a million elements, I could be waiting for half an hour, whereas the one liner up there takes less than a second. How could I solve this problem?
>>> from collections import OrderedDict
>>> items = [1, 2, 3, 'a', 2, 4, 'a']
>>> OrderedDict.fromkeys(items).keys()
[1, 2, 3, 'a', 4]

Python Values in Lists

I am using Python 3.0 to write a program. In this program I deal a lot with lists which I haven't used very much in Python.
I am trying to write several if statements about these lists, and I would like to know how to look at just a specific value in the list. I also would like to be informed of how one would find the placement of a value in the list and input that in an if statement.
Here is some code to better explain that:
count = list.count(1)
if count > 1
(This is where I would like to have it look at where the 1 is that the count is finding)
Thank You!
Check out the documentation on sequence types and list methods.
To look at a specific element in the list you use its index:
>>> x = [4, 2, 1, 0, 1, 2]
>>> x[3]
0
To find the index of a specific value, use list.index():
>>> x.index(1)
2
Some more information about exactly what you are trying to do would be helpful, but it might be helpful to use a list comprehension to get the indices of all elements you are interested in, for example:
>>> [i for i, v in enumerate(x) if v == 1]
[2, 4]
You could then do something like this:
ones = [i for i, v in enumerate(your_list) if v == 1]
if len(ones) > 1:
# each element in ones is an index in your_list where the value is 1
Also, naming a variable list is a bad idea because it conflicts with the built-in list type.
edit: In your example you use your_list.count(1) > 1, this will only be true if there are two or more occurrences of 1 in the list. If you just want to see if 1 is in the list you should use 1 in your_list instead of using list.count().
You can use list.index() to find elements in the list besides the first one, but you would need to take a slice of the list starting from one element after the previous match, for example:
your_list = [4, 2, 1, 0, 1, 2]
i = -1
while True:
try:
i = your_list[i+1:].index(1) + i + 1
print("Found 1 at index", i)
except ValueError:
break
This should give the following output:
Found 1 at index 2
Found 1 at index 4
First off, I would strongly suggest reading through a beginner’s tutorial on lists and other data structures in Python: I would recommend starting with Chapter 3 of Dive Into Python, which goes through the native data structures in a good amount of detail.
To find the position of an item in a list, you have two main options, both using the index method. First off, checking beforehand:
numbers = [2, 3, 17, 1, 42]
if 1 in numbers:
index = numbers.index(1)
# Do something interesting
Your other option is to catch the ValueError thrown by index:
numbers = [2, 3, 17, 1, 42]
try:
index = numbers.index(1)
except ValueError:
# The number isn't here
pass
else:
# Do something interesting
One word of caution: avoid naming your lists list: quite aside from not being very informative, it’ll shadow Python’s native definition of list as a type, and probably cause you some very painful headaches later on.
You can find out in which index is the element like this:
idx = lst.index(1)
And then access the element like this:
e = lst[idx]
If what you want is the next element:
n = lst[idx+1]
Now, you have to be careful - what happens if the element is not in the list? a way to handle that case would be:
try:
idx = lst.index(1)
n = lst[idx+1]
except ValueError:
# do something if the element is not in the list
pass
list.index(x)
Return the index in the list of the first item whose value is x. It is an error if there is no such item.
--
In the docs you can find some more useful functions on lists: http://docs.python.org/tutorial/datastructures.html#more-on-lists
--
Added suggestion after your comment: Perhaps this is more helpful:
for idx, value in enumerate(your_list):
# `idx` will contain the index of the item and `value` will contain the value at index `idx`

Categories