Process a list and output as list - python

I'm quite new to python and have a question about processing a list with a list as result.
Example:
list1 = ["vbhg12vbdf42vbsdh24", "dbsh13vdsj24lvk48"] #must become [['12','42','24'], ['13','24','48']]
list2 = (re.findall("\d+", str(list1))) # gives ['12', '42', '24', '13', '24', '48']
See comments. Any idea how I can do this?
Much appreciated.

First of all you need to specify that your pattern is a regex in your findall() function with add r at beginning of your pattern, then you need to loop over your list and apply the function on its element,You can use a list comprehension :
>>> list1 = ["vbhg12vbdf42vbsdh24", "dbsh13vdsj24lvk48"]
>>> import re
>>> [re.findall(r'\d+',i) for i in list1]
[['12', '42', '24'], ['13', '24', '48']]

How about:
result = []
for x in list1:
result.append(re.findall("\d+", x))
Or, as a list comprehension:
result = [re.findall("\d+", x) for x in list1]

Related

Nested list elements match with new list, if list contain the same add - python

I have nested list like below
mylist=[['2','3','100', '7'],[ '9', '13'],[ '21', '23', '25'],[],['9','24','45']]
i should compare with the new list if elements are present then print.
comp_list = ['2','3','100','9','13','25','45']
required output :
new_list=[['2','3','100'],['9','13'],['25'],[],['9','45']
i have something like below
for ele in mylist:
if ele in comp_list:
print(ele)
with this code the ele is not printed. can any one please help me to solve this. Thank you
You can try nested list comprehension as follow
mylist=[['2','3','100', '7'],[ '9', '13'],[ '21', '23', '25'],[],['9','24','45']]
comp_list = ['2','3','100','9','13','25','45']
new_list = [[y for y in i if y in comp_list] for i in mylist]
print(new_list)
If the comp_list is a large list it might be better to convert it to set before the comprehension because checking if a value is in a set is faster then in a list.
comp_set = set(comp_list)
new_list = [[y for y in i if y in comp_set] for i in mylist]
Output
[['2', '3', '100'], ['9', '13'], ['25'], [], ['9', '45']]
Below (classic nested for loop)
mylist = [['2','3','100', '7'],[ '9', '13'],[ '21', '23', '25'],[],['9','24','45']]
comp_list = ['2','3','100','9','13','25','45']
result = []
for entry in mylist:
tmp = []
for x in entry:
if x in comp_list:
tmp.append(x)
result.append(tmp)
print(result)
output
[['2', '3', '100'], ['9', '13'], ['25'], [], ['9', '45']]

Split and flatten a list of Strings and None values using a comprehension

Given a list which contains both strings and None values, in which some of the strings have embedded newlines, I wish to split the strings with newlines into multiple strings and return a flattened list.
I've written code to do this using a generator function, but the code is rather bulky and I'm wondering if it's possible to do it more concisely using a list comprehension or a function from the itertools module. itertools.chain doesn't seem to be able to decline to iterate any non-iterable elements.
def expand_newlines(lines):
r"""Split strings with newlines into multiple strings.
>>> l = ["1\n2\n3", None, "4\n5\n6"]
>>> list(expand_newlines(l))
['1', '2', '3', None, '4', '5', '6']
"""
for line in lines:
if line is None:
yield line
else:
for l in line.split('\n'):
yield l
You can use yield from.
def expand(lines):
for line in lines:
if isinstance(line,str):
yield from line.split('\n')
elif line is None:
yield line
list(expand(l))
#['1', '2', '3', None, '4', '5', '6']
Here's a single line, but I think #Ch3steR's solution is more readable.
from itertools import chain
list(chain.from_iterable(i.splitlines() if i is not None and '\n' in i else [i]
for i in lines))
You could use itertools.chain if you did the following
import itertools
def expand_newlines(lines):
return itertools.chain.from_iterable(x.split("\n") if x else [None]
for x in lines)
Using more_itertools.collapse to flatten nested lists:
Given
import more_itertools as mit
lst = ["1\n2\n3", None, "7\n8\n9"]
Demo
list(mit.collapse([x.split("\n") if x else x for x in lst ]))
# ['1', '2', '3', None, '7', '8', '9']
more_itertools is a third-party package. Install via > pip install more_itertools.
If you might modify list inplace then you might do:
lst = ["1\n2\n3", None, "4\n5\n6"]
for i in range(len(lst))[::-1]:
if isinstance(lst[i], str):
lst[i:i+1] = lst[i].split("\n")
print(lst) # ['1', '2', '3', None, '4', '5', '6']
this solution utilize fact that you might not only get python's list slices, but also assign to them. It moves from right to left, as otherwise I would need to keep count of additional items, which would make it harder.
Similar to #blueteeth's answer but more concise by way of inverting the logic:
import itertools
chainfi = itertools.chain.from_iterable
def expand_newlines(lines):
r"""Split strings with newlines into multiple strings.
>>> l = ["1\n2\n3", None, "4\n5\n6"]
>>> list(expand_newlines(l))
['1', '2', '3', None, '4', '5', '6']
"""
return chainfi([None] if l is None else l.split('\n') for l in lines)
None is the special case so that's what we should be checking for.
This is concise enough that I wouldn't even bother writing a function for it—I just kept it in the function to confirm it works via doctest.

Replace the particular value of array by some other value using python for loop

staff_text=['31','32']
staffing_title = ['14','28','14','20']
I have two array like above.and i want output like
staffing_title = ['31','28','32','20']
So basically whenever 14 comes in staffing_title array it replace by staff_text values.
ex if first 14 comes replace by 31,When second 14 comes replace by 32 and so on
Here is the one liner using list comprehension :
>>> staffing_title = ['14', '28', '14', '20']
>>> staff_text=['31','32']
>>> res = [staff_text.pop(0) if item == str(14) else item for item in staffing_title ]
>>> print(res)
['31', '28', '32', '20']
The following will do it:
>>> [t if t != '14' else staff_text.pop() for t in staffing_title]
['32', '28', '31', '20']
Note that this modifies staff_text, so you might want to make it operate on a copy.
This code assumes that there are at least as many elements in staff_text as there are '14' strings in staffing_title (but then you don't specify what should happen if there aren't).

I want to move a item to first index in list. How to simplify code?

This is my code.
lst=['0','1','2','3','4']
i = lst.index('2')
lst.pop(i)
tmp=[]
tmp.append('2')
tmp.extend(lst)
lst = tmp
print lst #output:['2','0','1','3','4']
Now I want to write pretty code. I think it may be to have room for improvement.So, I hope anyone who can explain and instruct me.Thanks!
sorted([0,1,2,3,4,5], key=lambda x: x == 2, reverse=True)
As an alternative answer you can use slicing :
>>> i = lst.index('2')
>>> ['2']+lst[:i]+lst[i+1:]
['2', '0', '1', '3', '4']
You can embed it inside a function :
>>> def move(elem,l):
... i = l.index(elem)
... return [elem]+lst[:i]+lst[i+1:]
...
>>> move('2',lst)
['2', '0', '1', '3', '4']
Donig it in place (altering the list):
lst = lst.pop(lst.index(2)) and (not lst.insert(0, 2)) and lst
Creating a new list for the result:
[2] + (lst.pop(lst.index(2)) and lst)

python list of numbers converted to string incorrectly

For some reason, when I do the code...
def encode():
result2 = []
print result
for x in result:
result2 += str(x)
print result2
I get...
[123, 456, 789]
['1', '2', '3', '4', '5', '6', '7', '8', '9']
How do I get it to return ['123', '456', '789']?
Thanks!
How about:
result2 = [str(x) for x in result]
The reason you are getting what you are getting is the += is doing list concatenation. Since str(123) is '123', which can be seen as ['1', '2', '3'], when you concatenate that to the empty list you get ['1', '2', '3'] (same thing for the other values).
For it to work doing it your way, you'd need:
result2.append(str(x)) # instead of result2 += str(x)
The functional method is to use list(map(str, lst)):
lst = [123, 456, 789]
res = list(map(str, lst))
print(res)
# ['123', '456', '789']
Performance is slightly better than a list comprehension.
The problem is that when you use += on a list, it expects the thing on the other side of the operator to be a list or some other kind of iterable. So you could do this:
>>> def encode():
... result2 = []
... print result
... for x in result:
... result2 += [str(x)]
... print result2
...
>>> result = [123, 456, 789]
>>> encode()
[123, 456, 789]
['123', '456', '789']
But when you do this:
result2 += str(x)
Python assumes you meant to treat the result of str(x) as an iterable, so before extending result2, it effectively* converts the string into a list of characters, as in the below example:
>>> [list(str(x)) for x in result]
[['1', '2', '3'], ['4', '5', '6'], ['7', '8', '9']]
As NullUserException suggested, a quick way to convert the items in a list is to use a list comprehension. In this case, just remove the list call above.
*To be precise, it converts the result of str(x) to an iterator (as by calling iter() -- or, as eryksun pointed out, by calling the the corresponding C API function PyObject_GetIter, though of course that only applies to cpython). Since iteration over a string is actually iteration over the individual characters in the string, each character gets added to the list separately.
Using map http://docs.python.org/library/functions.html#map
In [2]: input_list = [123, 456, 789]
In [3]: output_list = map(lambda x:str(x), input_list)
In [4]: output_list
Out[5]: ['123', '456', '789']

Categories