Order of python generator expression - python

I have an example where the iteration order of a python generator expression seems to be different from the analogous list comprehension and generator function.
For example, the code
n = 10
d = {i : str(i) for i in range(n)}
for i in d:
print d[i],
print
def func_gen(d):
for i in range(n):
yield d[i]
print(list(func_gen(d)))
g = [d[i] for i in range(n)]
print(g)
g = {d[i] for i in range(n)}
print(list(g))
has the output
0 1 2 3 4 5 6 7 8 9
['0', '1', '2', '3', '4', '5', '6', '7', '8', '9']
['0', '1', '2', '3', '4', '5', '6', '7', '8', '9']
['1', '0', '3', '2', '5', '4', '7', '6', '9', '8']
I would expect the generator expression to produce an ordered output like it does with the list comprehension. Is there something about generator expressions that
says the order isn't guaranteed?
Why is the order for the generator expression different from the others, even though the constructs are almost identical? It isn't even the same order as iterating through the dictionary, so it doesn't seem like
it's deferring to that.
I'm seeing the same behavior in Python 2 and 3.

Dicts aren't ordered. You can't rely on their items to come back in any particular order, even between function calls.

Related

List Comprehension - Conditional [duplicate]

This question already has answers here:
How do I iterate through two lists in parallel?
(8 answers)
Closed 22 days ago.
For these 2 lists:
A=['3.40', '4.00', '151.00', '8.00', '81.00', '23.00', '17.00', '8.50', '5.00', '151.00', 'SCR', 'SCR', '13.00']
B=['11', '5', '2', '4', '6', '9', '7', '8', '10', '1', '12', '10', '3']
The desired output is:
C=['11', '5', '2', '4', '6', '9', '7', '8', '10', '1', '3']
So - list 'A' and list 'B' are the same length. List 'C' is the same as list 'B' - but does not have the values where 'SCR' exists in list 'A'.
My attempt at this is:
C = [x for x in B if x in A!='SCR']
Thankyou
just zip them together:
C = [b for a,b in zip(A,B) if a != 'SCR']
Based on what I think you're trying to accomplish, I think you would need this:
C = [B[x] for x in range(len(B)) if A[x] != 'SCR']
This is straightforward using the built-in enumerate function:
[x for (idx, x) in enumerate(B) if A[idx] == 'SCR']

Python: How to convert a set of strings that contains commas represented as an element of a list to a sub-list?

I have a list that contains a set of strings like this:
list = ['235,ACCESS,19841136,22564960,4291500,20,527434,566876','046,ALLOWED,24737321,27863065,1086500,3,14208500,14254500']
I'm trying to make the elements of the list a sublist but without splitting the string.
I tried new_list = list(map(list, list)). This is the result taking as reference the first element of the list:
print(new_list[0]):
[['2', '3', '5', ',', 'A', 'C', 'C', 'E', 'S',',','1', '9', '8', '4', '1', '1', '3', '6', ',', '2', '2', '5', '6', '4', '9', '6', '0', ',', '4', '2', '9', '1', '5', '0', '0', ',', '2', '0', ',', '5', '2', '7', '4', '3', '4', ',', '5', '6', '6', '8', '7', '6']]
I would like this output:
print(new_list[0]):
[[235,'ACCESS',19841136,22564960,4291500,20,527434,566876]]
Thanks in advance for your help!
You can try split() with delimiter , like this -
new_list = [i.split(',') for i in list]
print (new_list[0])
Output:
['235', 'ACCESS', '19841136', '22564960', '4291500', '20', '527434', '566876']
One thing is that here the numbers are also represented as string. If you want integers instead you can use isdigit() method like this -
new_list = [[int(e) if e.isdigit() else e for e in i.split(',') ]for i in list]
print(new_list[0])
Output:
[235, 'ACCESS', 19841136, 22564960, 4291500, 20, 527434, 566876]
Also, please try to avoid naming your list list

how to convert parts of a large list and divide up into smaller, simpler lists? [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 3 years ago.
Improve this question
I have a large list an example of this list would be:
list = ['1', '2', '3', 'x', '4', '5', '6', 'x', '7', '8', '9', 'x']
I am struggling to create separate lists from this total list value separated by the value 'x'.
So for example, I need the above list to be converted to this:
list1 = ['1', '2', '3',]
list2 = ['4', '5', '6',]
list3 = ['7', '8', '9',]
Thank you for any help that you can give.
You can use a temporary list to store the values between 'x' and then use a condition to find 'x' and load the list to your new set of list
my_list = ['1', '2', '3', 'x', '4', '5', '6', 'x', '7', '8', '9', 'x']
new_list = []
temp_list = []
for value in my_list :
if value != 'x':
temp_list.append(value)
else:
new_list.append(temp_list)
temp_list = []
for sub_list in new_list:
print(sub_list)
Results:
['1', '2', '3']
['4', '5', '6']
['7', '8', '9']
Just for fun here is a version using all kinds of fun methods but IMO harder to follow.
test_list = ['1', '2', '3', 'x', '4', '5', '6', 'x', '7', '8', '9', 'x']
idx_list = [idx + 1 for idx, val in enumerate(test_list) if val == 'x']
res = [test_list[i: j] for i, j in zip([0] + idx_list, idx_list +
([len(test_list)] if idx_list[-1] != len(test_list) else []))]
print(res)
Her'e a slightly more general version using groupby that will work for all iterables:
from itertools import groupby
def split(iterable, delimiter):
return [list(v) for k, v in groupby(iterable, delimiter.__eq__) if not k]
l = ['1', '2', '3', 'x', '4', '5', '6', 'x', '7', '8', '9', 'x']
print(split(l, 'x'))
# [['1', '2', '3'], ['4', '5', '6'], ['7', '8', '9']]
You can do this very efficiently by cleverly using strings. I convert the list to a string, so I can use the split function which splits it in sublists based on a part of the string. I than convert those back to lists and ignore the last empty one.
l = ['1', '2', '3', 'x', '4', '5', '6', 'x', '7', '8', '9', 'x']
s = "".join(l)
list1,list2,list3 = [list(substring) for substring in s.split('x')][:-1] #To skip the empty list from the trailing 'x'

Python - iterating over nested loop

First off i am certain that such a basic thing has been asked before, but i could not find a post about it.
I have this piece of example data:
'192.168.244.213': ['8', '4', '3', '1', '6', '5', '3', '2', '6', '5'],
'192.168.244.214': ['6', '8', '7', '6', '5', '4', '2', '7', '5', '5'],
'192.168.244.215': ['4', '10', '0', '8', '7', '0', '4', '3', '2', '6'],
'192.168.244.230': ['0', '0', '0', '0', '0', '0', '0', '0', '0', '0']
And i want to print out every line (each line is one dictionary key-value pair) that has a list-value whose list contains any amount of items that is not 0 (in this case, every line except the 4th)
I just cant seem to figure out this seemingly simple thing - what i tried before was those two things:
for i in d.keys():
if "0" not in d[i]:
print(i, d[i])
This one shows only lists that do not contain 0 AT ALL - so the third line would not be shown, even though it contains non-0 values
for i in d.keys():
for j in d[i]:
if j is not "0":
print(i, d[i])
This one DOES show me what i want, but as you can tell, it prints every result way too often - one print for every list value that is not 0.
You can simply iterate over like
def all_zero(arr):
for i in arr:
if i != 0:
return False
else:
return True
You can call it on all the lists one by one.
Use a dictionary-comprehension:
d = {'192.168.244.213': ['8', '4', '3', '1', '6', '5', '3', '2', '6', '5'],
'192.168.244.214': ['6', '8', '7', '6', '5', '4', '2', '7', '5', '5'],
'192.168.244.215': ['4', '10', '0', '8', '7', '0', '4', '3', '2', '6'],
'192.168.244.230': ['0', '0', '0', '0', '0', '0', '0', '0', '0', '0']}
result = {k: v for k, v in d.items() if not all(x == '0' for x in v)}
# {'192.168.244.213': ['8', '4', '3', '1', '6', '5', '3', '2', '6', '5'],
# '192.168.244.214': ['6', '8', '7', '6', '5', '4', '2', '7', '5', '5'],
# '192.168.244.215': ['4', '10', '0', '8', '7', '0', '4', '3', '2', '6']}
The above code generates a new dictionary which omits all items where values are all zeros.
Now that you have a dictionary, you can easily do an iteration like so:
for k, v in result.items():
print(k, v)
Your bug is basically just a missing break:
for i in d.keys():
for j in d[i]:
if j != "0":
print(i, d[i])
break
However, for conciseness I would recommend you check out the any() function, which does exactly what you want: Return true if any of the elements of the iterable are true (when cast to booleans).
Eg:
for i in d.keys():
if any(j != "0" for j in d[i]):
print(i, d[i])
(The j is not "0" generator is only necessary because you have string values. For an int array, any(d[i]) would work.)
Even more "Pythonic" would be removing the need for a dictionary lookup:
for i, d_i in d.items():
if any(j != "0" for j in d_i):
print(i, d_i)
I like the other answers but I feel like you can get away with something like this as well:
for i in d.keys():
#If there are as many zeroes as there are elements in the list...
if d[i].count(0) == len(d[i]):
#...You might as well skip it :)
continue
print(d[i])
for i in d.keys():
all_zero = True
for j in d[i]:
if j is not "0":
all_zero = False
break
if not all_zero:
print(i, d[i])
This may work for almost every language :)
Have a look at how I could accomplish this.
d = {
'192.168.244.213': ['8', '4', '3', '1', '6', '5', '3', '2', '6', '5'],
'192.168.244.214': ['6', '8', '7', '6', '5', '4', '2', '7', '5', '5'],
'192.168.244.215': ['4', '10', '0', '8', '7', '0', '4', '3', '2', '6'],
'192.168.244.230': ['0', '0', '0', '0', '0', '0', '0', '0', '0', '0']
}
for key in d.keys():
if all( item == '0' for item in d[key]):
pass
else:
print(key, d[key])
You should use all in this case, consider following example:
digits = ['0', '2', '0', '4', '7', '5', '0', '3', '2', '6']
zeros = ['0', '0', '0', '0', '0', '0', '0', '0', '0', '0']
print(all([k=='0' for k in digits])) #gives False
print(all([k=='0' for k in zeros])) #gives True
Please remember to deliver [k=='0' for k in ...] to all, as delivering list directly would give True for both digits and zeros, as both contain at least one non-empty str (str of length 1 or greater).

unexpected results while calculating permutations while using itertools.permutation

Given string is '0123456789'.
I wanted to generate its one millionth permutation(1000000).
I wanted to give itertools.permutations a first try:
In [85]: import itertools
In [86]: a = list(itertools.permutations('0123456789'))
In [87]: a[1]
Out[87]: ('0', '1', '2', '3', '4', '5', '6', '7', '9', '8')
In [88]: a[1000000]
Out[88]: ('2', '7', '8', '3', '9', '1', '5', '6', '0', '4')
However if i run the following code:
def perm(S, perms=[], current=[], maximum=None):
if maximum and len(perms) > maximum:
return
size = len(S)
for i in range(size):
subset = list(S)
del(subset[i])
tmp_current = list(current)
tmp_current.append(S[i])
if size > 1:
perm(subset, perms, tmp_current, maximum)
else:
perms.append(tmp_current)
if maximum:
if len(perms) == maximum:
print tmp_current
return
perm('0123456789', maximum=1000000)
# the result is ['2', '7', '8', '3', '9', '1', '5', '4', '6', '0']
The answer from itertools.permutations and from the above psuedo code does not match.
[2783915604] from itertools
[2783915460] from the snippet above
The second answer is the correct answer. Could anyone please explain me why the first process is not yielding a correct result?
You messed up with indexes:
>>> a[999999]
('2', '7', '8', '3', '9', '1', '5', '4', '6', '0')
You code quits when generates 1m result. And 1m element in a list has index 999999.

Categories

Resources