Is there any single function to print an iterable's values? - python

Suppose I have an iterable:
var = "ABCDEF"
I get the iterable like this:
it = itertools.combinations(var,2)
Is there any single function to print all values of iterables like
printall(it)
rather than using the for loop?

This rather depends what you want, if you want to print out all the values, you need to compute them - an iterable doesn't guarantee the values are computed until after they are all requested, so the easiest way to achieve this is to make a list:
print(list(iterable))
This will print out the items in the normal list format, which may be suitable. If you want each item on a new line, the best option is, as you mentioned, a simple for loop:
for item in iterable:
print(item)
If you don't need the data in a specific format, but just need it to be readable (not all on one line, for example), you may want to check out the pprint module.
A final option, which I don't really feel is optimal, but mention for completeness, is possible in 3.x, where the print() function is very flexible:
print(*iterable, sep="\n")
Here we unpack the iterable as the arguments to print() and then make the separator a newline (as opposed to the usual space).

You could use the str.join method and join each element of the iterable on a new line.
print('\n'.join(it))

You can use format which will allow each element to be formated as you please:
>>> print '\n'.join('{:>10}'.format(e) for e in iter([1,2,'1','2',{1:'1'}]))
1
2
1
2
{1: '1'}
Each element does not need to be a string necessarily, but must have a __repr__ method if it is not a string.
You can then easily write the function you desire:
>>> def printall(it,w): print '\n'.join('{:>{w}}'.format(e,w=w) for e in it)
>>> printall([1,2,'3','4',{5:'6'}],10)
1
2
3
4
{5: '6'}
I am using a list, but any iterable would do.

You can use chain() function from itertools to create iterator for var data and then just unpack using * operator of iterator
>>> from itertools import chain
>>> var = 'ABCDEF'
>>> print(*chain(var))
A B C D E F
>>> print(*chain(var), sep='\n')
A
B
C
D
E
F
If you just need to iterate over existing data and print it out again you can use star operator * for this
>>> print(*var)
A B C D E F
>>> print(*var, sep='\n')
A
B
C
D
E
F

If you insist on a solution which iterates without a for loop and works for infinite iterators:
from more_itertools import consume
def printall(it):
consume(map(print, it))
Instead of the for loop we have consume here.
Note that in this case the iterator is consumed while printing.
This, of course, works for infinite iterators as well:
from itertools import count
printall(count())
Just for fun. :)

Related

Differentiating a tuple from a tuple of tuples

I have a tuple, and a tuple of tuples.
import numpy as np
a = ("Control", "Group1")
b = (("Control", "Group1"), ("Control", "Group1", "Group2))
How can I tell that a is fundamentally different from b? Both
print(len(a))
print(np.shape(a))
print(len(np.shape(a)))
and
print(len(b))
print(np.shape(b))
print(len(np.shape(b)))
produce the same output:
2
(2,)
1
Thanks in advance again!
You cannot, because they are not fundamentally different.
What should happen for the following?
c = (("Foo", "bar"), "baz")
It’s also a tuple, and it contains both "bare" values as well as another tuple.
If you need to detect tuples which only consist of tuples, use:
if all(isinstance(element, tuple) for element in a)
If you need to detect tuples which only consist of non-tuples, use:
if not any(isinstance(element, tuple) for element in a)
Both of the above are have a time complexity of O(n) (with n being the number of elements in a), which may not be desirable depending from where your data is coming. It is however unavoidable, unless you are willing to take the risk not actually having tuples of tuples.
Depending on what you’re doing with your data, you might actually want to check for a sequence of sequences. In that case, you should use the Sequence ABC (Python 2):
import collections.abc
if all(isinstance(element, collections.abc.Sequence) for element in a)
Use the equality operator, ==:
>>> a = ("Control", "Group1")
>>> b = (("Control", "Group1"), ("Control", "Group1", "Group2"))
>>> a == b
False
If you just want a vague idea of the general structure, and the string elements won't contain parentheses, you can count the parentheses:
>>> str(a).count('(')
1
>>> str(b).count('(')
3

What is a better pythonic version of this conditional deleting?

i am refreshing my python (2.7) and i am discovering iterators and generators.
As i understood, they are an efficient way of navigating over values without consuming too much memory.
So the following code do some kind of logical indexing on a list:
removing the values of a list L that triggers a False conditional statement represented here by the function f.
I am not satisfied with my code because I feel this code is not optimal for three reasons:
I read somewhere that it is better to use a for loop than a while loop.
However, in the usual for i in range(10), i can't modify the value of 'i' because it seems that the iteration doesn't care.
Logical indexing is pretty strong in matrix-oriented languages, and there should be a way to do the same in python (by hand granted, but maybe better than my code).
Third reason is just that i want to use generator/iterator on this example to help me understand.
Third reason is just that i want to use generator/iterator on this example to help me understand.
TL;DR : Is this code a good pythonic way to do logical indexing ?
#f string -> bool
def f(s):
return 'c' in s
L=['','a','ab','abc','abcd','abcde','abde'] #example
length=len(L)
i=0
while i < length:
if not f(L[i]): #f is a conditional statement (input string output bool)
del L[i]
length-=1 #cut and push leftwise
else:
i+=1
print 'Updated list is :', L
print length
This code has a few problems, but the main one is that you must never modify a list you're iterating over. Rather, you create a new list from the elements that match your condition. This can be done simply in a for loop:
newlist = []
for item in L:
if f(item):
newlist.append(item)
which can be shortened to a simple list comprehension:
newlist = [item for item in L if f(item)]
It looks like filter() is what you're after:
newlist = filter(lambda x: not f(x), L)
filter() filters (...) an iterable and only keeps the items for which a predicate returns True. In your case f(..) is not quite the predicate but not f(...).
Simpler:
def f(s):
return 'c' not in s
newlist = filter(f, L)
See: https://docs.python.org/2/library/functions.html#filter
Never modify a list with del, pop or other methods that mutate the length of the list while iterating over it. Read this for more information.
The "pythonic" way to filter a list is to use reassignment and either a list comprehension or the built-in filter function:
List comprehension:
>>> [item for item in L if f(item)]
['abc', 'abcd', 'abcde']
i want to use generator/iterator on this example to help me understand
The for item in L part is implicitly making use of the iterator protocol. Python lists are iterable, and iter(somelist) returns an iterator .
>>> from collections import Iterable, Iterator
>>> isinstance([], Iterable)
True
>>> isinstance([], Iterator)
False
>>> isinstance(iter([]), Iterator)
True
__iter__ is not only being called when using a traditional for-loop, but also when you use a list comprehension:
>>> class mylist(list):
... def __iter__(self):
... print('iter has been called')
... return super(mylist, self).__iter__()
...
>>> m = mylist([1,2,3])
>>> [x for x in m]
iter has been called
[1, 2, 3]
Filtering:
>>> filter(f, L)
['abc', 'abcd', 'abcde']
In Python3, use list(filter(f, L)) to get a list.
Of course, to filter a list, Python needs to iterate over it, too:
>>> filter(None, mylist())
iter has been called
[]
"The python way" to do it would be to use a generator expression:
# list comprehension
L = [l for l in L if f(l)]
# alternative generator comprehension
L = (l for l in L if f(l))
It depends on your context if a list or a generator is "better" (see e.g. this so question). Because your source data is coming from a list, there is no real benefit of using a generator here.
For simply deleting elements, especially if the original list is no longer needed, just iterate backwards:
Python 2.x:
for i in xrange(len(L) - 1, -1, -1):
if not f(L[i]):
del L[i]
Python 3.x:
for i in range(len(L) - 1, -1, -1):
if not f(L[i]):
del L[i]
By iterating from the end, the "next" index does not change after deletion and a for loop is possible. Note that you should use the xrange generator in Python 2, or the range generator in Python 3, to save memory*.
In cases where you must iterate forward, use your given solution above.
*Note that Python 2's xrange will break if there are >= 2 ** 32 - 1 elements. Python 3's range, as well as the less efficient Python 2's range do not have this limitation.

Explanation regarding "generator object"

Could some one please explain why this code:
A = [1,2,3,4]
B = ((element) for element in A)
print(B)
produces: <generator object <genexpr> at 0x0319B490>
while this code:
A = [1,2,3,4]
for element in A:
print(A)
produces:
1
2
3
4
They seem to be the same to me but they are obviously different. I can't figure out the difference between them.
Thanks.
The first code is a generator expression, hence it will create a generator object at a certain memory address. If you want to use list comprehension then use [] as per:
A = [1,2,3,4]
B = [element for element in A]
print(B)
# [1, 2, 3, 4]
This list comprehension is equivalent to:
A = [1,2,3,4]
B = []
for element in A:
B.append(element)
The first is not a loop but a generator expresion so will printing B it shows us the object ref.
The second one Is a loop, it iterates over the elements and print them all.
Try doing this, you can iterate over a generator:
A = [1,2,3,4]
B = ((element) for element in A)
for e in B:
print(e)
This will result in the same as your second expresion:
for e in A:
print(e)
Notice that you can only iterate once until the generator is exausted.
The fundamental difference between the two is that a generator expression defines an object that will generate values as you loop. In other words, the values will be generated on each iteration and consumed on demand. With a list comprehension, the values are created up-front and will consume as much memory as is required to hold all the values in memory at once.
It's easy to look at these two constructs as being the exact same thing but in the case of the generator, you are consuming the values on demand in a lazy way. This is very useful because you don't have pay the cost of memory to hold all of the data up-front.

Is there a 'foreach' function in Python 3?

When I meet the situation I can do it in javascript, I always think if there's an foreach function it would be convenience. By foreach I mean the function which is described below:
def foreach(fn,iterable):
for x in iterable:
fn(x)
they just do it on every element and didn't yield or return something,i think it should be a built-in function and should be more faster than writing it with pure Python, but I didn't found it on the list,or it just called another name?or I just miss some points here?
Maybe I got wrong, cause calling an function in Python cost high, definitely not a good practice for the example. Rather than an out loop, the function should do the loop in side its body looks like this below which already mentioned in many python's code suggestions:
def fn(*args):
for x in args:
dosomething
but I thought foreach is still welcome base on the two facts:
In normal cases, people just don't care about the performance
Sometime the API didn't accept iterable object and you can't rewrite its source.
Every occurence of "foreach" I've seen (PHP, C#, ...) does basically the same as pythons "for" statement.
These are more or less equivalent:
// PHP:
foreach ($array as $val) {
print($val);
}
// C#
foreach (String val in array) {
console.writeline(val);
}
// Python
for val in array:
print(val)
So, yes, there is a "foreach" in python. It's called "for".
What you're describing is an "array map" function. This could be done with list comprehensions in python:
names = ['tom', 'john', 'simon']
namesCapitalized = [capitalize(n) for n in names]
Python doesn't have a foreach statement per se. It has for loops built into the language.
for element in iterable:
operate(element)
If you really wanted to, you could define your own foreach function:
def foreach(function, iterable):
for element in iterable:
function(element)
As a side note the for element in iterable syntax comes from the ABC programming language, one of Python's influences.
Other examples:
Python Foreach Loop:
array = ['a', 'b']
for value in array:
print(value)
# a
# b
Python For Loop:
array = ['a', 'b']
for index in range(len(array)):
print("index: %s | value: %s" % (index, array[index]))
# index: 0 | value: a
# index: 1 | value: b
map can be used for the situation mentioned in the question.
E.g.
map(len, ['abcd','abc', 'a']) # 4 3 1
For functions that take multiple arguments, more arguments can be given to map:
map(pow, [2, 3], [4,2]) # 16 9
It returns a list in python 2.x and an iterator in python 3
In case your function takes multiple arguments and the arguments are already in the form of tuples (or any iterable since python 2.6) you can use itertools.starmap. (which has a very similar syntax to what you were looking for). It returns an iterator.
E.g.
for num in starmap(pow, [(2,3), (3,2)]):
print(num)
gives us 8 and 9
The correct answer is "python collections do not have a foreach". In native python we need to resort to the external for _element_ in _collection_ syntax which is not what the OP is after.
Python is in general quite weak for functionals programming. There are a few libraries to mitigate a bit. I helped author one of these infixpy
pip install infixpy https://pypi.org/project/infixpy/
from infixpy import Seq
(Seq([1,2,3]).foreach(lambda x: print(x)))
1
2
3
Also see: Left to right application of operations on a list in Python 3
Here is the example of the "foreach" construction with simultaneous access to the element indexes in Python:
for idx, val in enumerate([3, 4, 5]):
print (idx, val)
Yes, although it uses the same syntax as a for loop.
for x in ['a', 'b']: print(x)
This does the foreach in python 3
test = [0,1,2,3,4,5,6,7,8,"test"]
for fetch in test:
print(fetch)
Look at this article. The iterator object nditer from numpy package, introduced in NumPy 1.6, provides many flexible ways to visit all the elements of one or more arrays in a systematic fashion.
Example:
import random
import numpy as np
ptrs = np.int32([[0, 0], [400, 0], [0, 400], [400, 400]])
for ptr in np.nditer(ptrs, op_flags=['readwrite']):
# apply random shift on 1 for each element of the matrix
ptr += random.choice([-1, 1])
print(ptrs)
d:\>python nditer.py
[[ -1 1]
[399 -1]
[ 1 399]
[399 401]]
If I understood you right, you mean that if you have a function 'func', you want to check for each item in list if func(item) returns true; if you get true for all, then do something.
You can use 'all'.
For example: I want to get all prime numbers in range 0-10 in a list:
from math import sqrt
primes = [x for x in range(10) if x > 2 and all(x % i !=0 for i in range(2, int(sqrt(x)) + 1))]
If you really want you can do this:
[fn(x) for x in iterable]
But the point of the list comprehension is to create a list - using it for the side effect alone is poor style. The for loop is also less typing
for x in iterable: fn(x)
I know this is an old thread but I had a similar question when trying to do a codewars exercise.
I came up with a solution which nests loops, I believe this solution applies to the question, it replicates a working "for each (x) doThing" statement in most scenarios:
for elements in array:
while elements in array:
array.func()
If you're just looking for a more concise syntax you can put the for loop on one line:
array = ['a', 'b']
for value in array: print(value)
Just separate additional statements with a semicolon.
array = ['a', 'b']
for value in array: print(value); print('hello')
This may not conform to your local style guide, but it could make sense to do it like this when you're playing around in the console.
In short, the functional programming way to do this is:
def do_and_return_fn(og_fn: Callable[[T], None]):
def do_and_return(item: T) -> T:
og_fn(item)
return item
return do_and_return
# where og_fn is the fn referred to by the question.
# i.e. a function that does something on each element, but returns nothing.
iterable = map(do_and_return_fn(og_fn), iterable)
All of the answers that say "for" loops are the same as "foreach" functions are neglecting the point that other similar functions that operate on iters in python such as map, filter, and others in itertools are lazily evaluated.
Suppose, I have an iterable of dictionaries coming from my database and I want to pop an item off of each dictionary element when the iterator is iterated over. I can't use map because pop returns the item popped, not the original dictionary.
The approach I gave above would allow me to achieve this if I pass lambda x: x.pop() as my og_fn,
What would be nice is if python had a built-in lazy function with an interface like I constructed:
foreach(do_fn: Callable[[T], None], iterable: Iterable)
Implemented with the function given before, it would look like:
def foreach(do_fn: Callable[[T], None], iterable: Iterable[T]) -> Iterable[T]:
return map(do_and_return_fn(do_fn), iterable)
# being called with my db code.
# Lazily removes the INSERTED_ON_SEC_FIELD on every element:
doc_iter = foreach(lambda x: x.pop(INSERTED_ON_SEC_FIELD, None), doc_iter)
No there is no from functools import foreach support in python. However, you can just implement in the same number of lines as the import takes, anyway:
foreach = lambda f, iterable: (*map(f, iterable),)
Bonus:
variadic support: foreach = lambda f, iterable, *args: (*map(f, iterable, *args),) and you can be more efficient by avoiding constructing the tuple of Nones

What does [u'abcd', u'bcde'] mean in Python?

Used a loop to add a bunch of elements to a list with
mylist = []
for x in otherlist:
mylist.append(x[0:5])
But instead of the expected result ['x1','x2',...], I got: [u'x1', u'x2',...]. Where did the u's come from and why? Also is there a better way to loop through the other list, inserting the first six characters of each element into a new list?
The u means unicode, you probably will not need to worry about it
mylist.extend(x[:5] for x in otherlist)
The u means unicode. It's Python's internal string representation (from version ... ?).
Most times you don't need to worry about it. (Until you do.)
The answers above me already answered the "u" part - that the string is encoded in Unicode. About whether there's a better way to extract the first 6 letters from the items in a list:
>>> a = ["abcdefgh", "012345678"]
>>> b = map(lambda n: n[0:5], a);
>>> for x in b:
print(x)
abcde
01234
So, map applies a function (lambda n: n[0:5]) to each element of a and returns a new list with the results of the function for every element. More precisely, in Python 3, it returns an iterator, so the function gets called only as many times as needed (i.e. if your list has 5000 items, but you only pull 10 from the result b, lambda n: n[0:5] gets called only 10 times). In Python2, you need to use itertools.imap instead.
>>> a = [1, 2, 3]
>>> def plusone(x):
print("called with {}".format(x))
return x + 1
>>> b = map(plusone, a)
>>> print("first item: {}".format(b.__next__()))
called with 1
first item: 2
Of course, you can apply the function "eagerly" to every element by calling list(b), which will give you a normal list with the function applied to each element on creation.
>>> b = map(plusone, a)
>>> list(b)
called with 1
called with 2
called with 3
[2, 3, 4]

Categories