python extend or append a list when appropriate - python

Is there a simple way to append a list if X is a string, but extend it if X is a list? I know I can simply test if an object is a string or list, but I was wondering if there is a quicker way than this?

mylist.extend( [x] if type(x) == str else x )
or maybe the opposite would be safer if you want to catch things other than strings too:
mylist.extend( x if type(x) == list else [x] )

I do not think so. extend takes any iterable as input, and strings as well as lists are iterables in python.

buffer = ["str", [1, 2, 3], 4]
myList = []
for x in buffer:
if isinstance(x, str):
myList.append(x)
elif isinstance(x, list):
myList.extend(x)
else:
print("{} is neither string nor list".format(x))
A better way would be using try-except instead of isinstance()

Related

matching list structure other than map() in python

I am trying to write a recursive function that will perform some action on every object within the list and then output a new list that matches the structure of the processed list exactly. I had some help from users here, but in my example i tried strings which happen to be iterable and work well with map(). However when I am applying it to other data types like int that are not iterable, i get an error:
def process_list(_list):
new_list = []
for x in _list:
if is_list(x):
new_list.append(process_list(x))
else:
new_list.append(map(lambda y: y + 1, x))
return new_list
def is_list(l):
return type(l) == types.ListType
_list = [[0,1,2],[0,1,2],[0,1,2]],[0,1,2]]
i am using Integers as an example here because they are not iterable and i am expecting that map() will fail on a list of integers. Imagine any other data type that is not iterable. Is there another way to define this that will let me perform some function(s) on objects within the list and then create an output list that matches the input list?
thank you,
You are trying to iterate (by using the map() function) over x, which is not iterable in most cases. The reason you can do it for strings is because they are iterable objects in themselves, which is why you didn't run into this right away. You really don't need to use map() at all in your for loop... you could just do
for x in _list:
if is_list(x):
new_list.append(process_list(x))
else:
new_list.append(x+1)
Really the best thing you could do is use map directly:
def process_list(_list):
return map( lambda x: process_list(x) if type(x)==list else x+1, _list )
Try modifying the else clause so it performs simple addition on the item. No map or lambda required.
import types
def process_list(_list):
new_list = []
for x in _list:
if is_list(x):
new_list.append(process_list(x))
else:
new_list.append(x+1)
return new_list
def is_list(l):
return type(l) == types.ListType
_list = [[[0,1,2],[0,1,2],[0,1,2]],[0,1,2]]
print process_list(_list)
Result:
[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [1, 2, 3]]
If you want calls to process_list to look more like map, you can require an additional parameter, which indicates what kind of processing should be done.
import types
def process_list(func, _list):
new_list = []
for x in _list:
if is_list(x):
new_list.append(process_list(func, x))
else:
new_list.append(func(x))
return new_list
def is_list(l):
return type(l) == types.ListType
_list = [[[0,1,2],[0,1,2],[0,1,2]],[0,1,2]]
print process_list(lambda x: x+1, _list)
check with isinstance to see what the type is and base your logic on that:
def process_list(_list):
new_list = []
for x in _list:
if isinstance(x, list):
new_list.append(process_list(x))
elif isinstance(x, (int, float)):
new_list.append(x+1)
else:
new_list.append(map(lambda y: y + 1, x))
return new_list
You can also use collections.Iterable to find iterable elements after you have checked for a list, if you wanted to only call map on strings you would use isinstance(x, basestring) what you check for all depends on what you are trying to achieve:
from collections import Iterable
def process_list(_list):
new_list = []
for x in _list:
if isinstance(x, list):
new_list.append(process_list(x))
elif isinstance(x, Iterable):
new_list.append(map(lambda y: y + 1, x))
else:
new_list.append(x+1)
return new_list

Python Simple program iteration through list

I'm new to programming and I'm making a simple program to test.
Here is the code:
list1 = [1,2,d,,t,h,7,8]
for x in list1:
if x ==
I'm trying to iterate in my list and check to see which item is a string and which is
a number(I know its basic, but im new). So what would be a correct way to write this line
of code. All suggestions would help
In Python, use the builtin isinstance(variable, type) to test whether a variable is of a given type.
The type variable can also be a tuple of several types to test against.
Your list is a little messed up. If those letters are supposed to be strings, it should look like this:
list1 = [1,2,'d','t','h',7,8]
Otherwise they are referring to variables.
To check if number
for x in list1:
if isinstance(x, int):
...
To check if string
for x in list1:
if isinstance(x, str):
...
Combination
for x in list1:
if x.isinstance(x, int):
....
elif isinstance(x, str)L
....
This should print the type of each element in your list
for item in list1:
print type(item)
Assuming your list contains purely numbers and strings:
for x in list1:
if type(x) == str:
# do something
else:
# do something for numbers
Since everyone is giving answers similar to my old one (see below), I'll try something else.You can easily make 2 lists that separate ints and strings with Python's list comprehensions:
strings = [x for x in list1 if isinstance(x, str)]
intlist = [x for x in list1 if isinstance(x, int)]
Using list comprehensions made the code more compact and easier to understand.
Old response:
list1 = [1, 4, 5, '5', '3', 3, 'a']
for x in list1:
if(isinstance(x, str)):
print(str(x) + ' is a string.')
else:
print(str(x) + ' is not a string.')
You could try this one,
list1=[1,2,'d','t','h',7,8]
for data in list1:
if type(data) is str:
#do something with it
elif type(data) is int:
#do something with it
you can try something like this or any of those methods mentioned from other answers in the python interpreter to see it works -
>> type(1) is str
and you would get
>> False

Printing a list with string.format rounding for float members

If I have a list of the format ['ABC',0.1234,'DEF'] and I wanted to print it out doing something like
l = ['ABC',0.1234,'DEF']
print('\t'.join(map(str, l)))
But I would also like to round the float so that the output would be ABC\t0.12\tDEF.
I can do it with something like:
a,b,c = l
print('{}\t{:.2f}\t{}'.format(a,b,c))
But since l is just one member of a much larger list, I would like to be able to do this with a list comprehension or something more pythonic.
As mentioned in the comment, you can simply do this for a big list:
print('{}\t{:.2f}\t{}'.format(*l))
Note that .format() also supports indexing the list. Something like:
print('0[0] 0[1] 0[2]'.format(l))
Edit:
"The data structure here is a list of triplet lists. Is there any straightforward way to do string formatting on a unknown size list?"
You can try:
>>> print('\t'.join("{:.2f}".format(x) if isinstance(x, float) else str(x) for k
in l for x in k))
You could use:
print('\t'.join("{:.2f}".format(x) if isinstance(x, float) else str(x) for x in l))
You could define a function for this:
def float_or_str(x):
try:
return '{:.2f}'.format(x)
except ValueError:
return '{}'.format(x)
l = ['ABC',0.1234,'DEF']
print('\t'.join(map(float_or_str, l)))
yields
ABC 0.12 DEF

Remove single quotes from python list item

Actually quite simple question:
I've a python list like:
['1','2','3','4']
Just wondering how can I strip those single quotes?
I want [1,2,3,4]
Currently all of the values in your list are strings, and you want them to integers, here are the two most straightforward ways to do this:
map(int, your_list)
and
[int(value) for value in your_list]
See the documentation on map() and list comprehensions for more info.
If you want to leave the items in your list as strings but display them without the single quotes, you can use the following:
print('[' + ', '.join(your_list) + ']')
If that's an actual python list, and you want ints instead of strings, you can just:
map(int, ['1','2','3','4'])
or
[int(x) for x in ['1','2','3','4']]
Try this
[int(x) for x in ['1','2','3','4']]
[1, 2, 3, 4]
and to play safe you may try
[int(x) if type(x) is str else None for x in ['1','2','3','4']]

Python logic error?

Basically, I'm trying to flatten a list in my function but ignore that (you can also ignore the print functions I put in).
take x = [[1,2,3],4,5] to be my variable.
I call prob7(x) but the issue is that when type([1,2,3]) gets checked == list, it returns false. Why is that? I explicitly check this on the interpreter command line and it returns true. But inside the function, I get a false.
Just a bug that I missed because I'm sleepy or am I misunderstanding some part of the Python language? I run version 2.6 if it matters.
def prob7(list): # flatten a list
tempList = []
if list: # meaning if there are elements in the list and it is not empty
for i in list:
if type(i) != list:
print tempList,'if',i,type(i)==list
tempList.append(i)
else:
print tempList,'else',i
tempList.extend(prob7(i))
return tempList
Just not use 'list' as a variable name and use isinstance(var, list) instead of type(var) == list.
Please find corrected sample below.
def prob7(mylist): # flatten a list
tempList = []
if mylist: # meaning if there are elements in the list and it is not empty
for i in mylist:
if not isinstance(i, list):
print tempList, 'if', i, isinstance(i, list)
tempList.append(i)
else:
print tempList, 'else', i
tempList.extend(prob7(i))
return tempList
Or if you don't really required to use recursion and you don't care about values order then you can use something like this:
lVals = [[1,2,3],4,5, [1,[4,7]]]
def make_flat(mylist): # flatten a list
while any(isinstance(x, list) for x in mylist):
for i, val in enumerate(mylist):
if isinstance(val, list):
mylist.extend(mylist.pop(i))
break
return mylist
make_flat(lVals)
>>> [4, 5, 1, 2, 3, 1, 4, 7]
Artisom has your answer. In addtion, type checks are not very Pythonic. Duck typing often is the way to go. In case your elements are numbers only, the following does the job too, without explicit type checks but behavior checks:
def prob7(inlist): # flatten a list
outlist = []
for x in inlist:
try:
outlist += x
except TypeError:
outlist.append(x)
return outlist
Note that string elements in this implementation would behave like nested lists. Anyway, just wanted to illustrate what it means to expect behavior, not types.
Some alternate approaches:
# Iterative, but more functional-style
def flatten(a_list):
while any(isinstance(x, list) for x in a_list):
a_list = sum((x if isinstance(x, list) else [x] for x in a_list), [])
return a_list
# Using a generator recursively,
# then evaluating the generator to produce the list
# instead of explicitly appending each element.
def flatten_gen(a_list):
for x in a_list:
if isinstance(x, list):
for y in flatten_gen(x): yield y
else: yield x
def flatten(a_list): return list(flatten_gen(a_list))
The problem here is you are using a local variable name (list) that is the same as the global list type. You should change your variable name. Also, when checking types like that you can use the is operator.
type(l) is list
But here's my version of flatten.
def flatten(alist):
rv = []
for val in alist:
if isinstance(val, list):
rv.extend(flatten(val))
else:
rv.append(val)
return rv
This does not alter the original list, but returns a new list. This is consistent with most other patterns.

Categories

Resources