splitting a list in a better way using list comprehension - python

I have a simple list that I am splitting and concatenating. My code uses for loop and if condition and ugly. Can you suggest a better way using list comprehension?
My code
mylist = ['10.10.10.1','10.10.10.2,10.10.10.3,10.10.10.4,10.10.10.5','10.10.10.6']
mylist = [i.split(",") for i in mylist]
list =[]
for x,y in enumerate(mylist):
if len(y) == 1:
list.append(y[0])
else:
for z in y:
list.append(z)
print(list)
I am getting the below result and exactly the way i want
['10.10.10.1','10.10.10.2','10.10.10.3','10.10.10.4','10.10.10.5','10.10.10.6']

You want:
[s for string in mylist for s in string.split(',')]
Note, your original approach wouldn't be so bad if you just simplified. No need for enumerate and no need to check the length, so just:
final_list =[]
for sub in mylist:
for s in sub:
final_list.append(s)
By the way, you shouldn't shadow the built-in list. Use another name

I agree with #juanpa.arrivillaga. However hope we can avoid that second looping since he is checking for empty values returning while splitting
In [7]: s=['10.10.10.1','','10.10.10.2,10.10.10.3,10.10.10.4,10.10.10.5','10.10.10.6']
In [8]: [splitRec for rec in s for splitRec in rec.split(',') if splitRec]
Out[8]:
['10.10.10.1',
'10.10.10.2',
'10.10.10.3',
'10.10.10.4',
'10.10.10.5',
'10.10.10.6']
In [9]: s=['10.10.10.1',',,','10.10.10.2,10.10.10.3,10.10.10.4,10.10.10.5','10.10.10.6']
In [10]: [splitRec for rec in s for splitRec in rec.split(',') if splitRec]Out[10]:
['10.10.10.1',
'10.10.10.2',
'10.10.10.3',
'10.10.10.4',
'10.10.10.5',
'10.10.10.6']

Not a comprehension, but good anyway, I think.
','.join(mylist).split(',')

You can first just split each string on ',':
>>> mylist = ['10.10.10.1','10.10.10.2,10.10.10.3,10.10.10.4,10.10.10.5','10.10.10.6']
>>> split_str = [x.split(',') for x in mylist]
>>> split_str
[['10.10.10.1'], ['10.10.10.2', '10.10.10.3', '10.10.10.4', '10.10.10.5'], ['10.10.10.6']]
Then if you want to flatten it, you can use itertools.chain.from_iterable:
>>> from itertools import chain
>>> list(chain.from_iterable(split_str))
['10.10.10.1', '10.10.10.2', '10.10.10.3', '10.10.10.4', '10.10.10.5', '10.10.10.6']

Related

How delete a element of a list and save the original index of deleted element?

I want delete some elements of one list equal to a value:
I can do it :
List =[1,2,3.....]
List = [x for x in List if x != 2]
How can i save the indexs of the deleted elements ?
I want to use this index to delete elements of another list.
Simplest solution is to make a list of indices to keep, then use that to strip the elements from both of your lists. itertools provides a handy compress utility to apply the indices to keep quickly:
from itertools import compress
tokeep = [x != 2 for x in List]
List = list(compress(List, tokeep))
otherlist = list(compress(otherlist, tokeep))
Alternatively (and frankly more clearly) you can just use one loop to strip both inputs; listcomps are fun, but sometimes they're not the way to go.
newlist = []
newotherlist = []
for x, y in zip(List, otherlist):
if x != 2:
newlist.append(x)
newotherlist.append(y)
which gets the same effect in a single pass. Even if it does feel less overtly clever, it's very clear, which is a good thing; brevity for the sake of brevity that creates complexity is not a win.
And now, to contradict that last paragraph, the amusingly overtly clever and brief solution to one-line this:
List, otherlist = map(list, zip(*[(x, y) for x, y in zip(List, otherlist) if x != 2]))
For the love of sanity, please don't actually use this, I just had to write it for funsies.
You can also leverage enumerate
for index, val in enumerate(List):
if val == value:
del List[index]
break
print(index)
Based on documentation
list_first = ['d', 'a']
list_second = ['x', 'z']
def remove_from_lists(element):
index_deleted = list_first.index(element)
list_first.remove(element)
list_second.pop(index_deleted)
remove_from_lists('d')

How to sort list of strings

I have an initial list of strings:
List1 = ["2,6,4,5", "3,7,4,2"]
I would like each string to be sorted in ascending order:
Output = ["2,4,5,6", "2,3,4,7"]
May I know how do I do that?
You can try splitting, sort, then join
List1 = ["2,6,4,5", "3,7,4,2"]
sortedList = []
for s in List1:
nums = s.split(",")
nums.sort()
sortedList.append(",".join(nums))
Thanks for pointing out that the above doesn't work for numbers > 10 and negative numbers, I forgot that it was sorting with strings. Although the question didn't really specify, it makes sense that sorting should be based on number rather than string so update:
for s in List1:
nums = s.split(",")
nums = list(map(int, nums))
nums.sort()
nums = list(map(str, nums))
sortedList.append(",".join(nums))
You could make use of ast.literal_eval in order to evaluating the strings as Python values:
import ast
List1 = ["2,6,4,5", "3,7,4,2"]
print([",".join(map(str, sorted(ast.literal_eval(item)))) for item in List1])
Out:
['2,4,5,6', '2,3,4,7']
Here's a way to do it using list comprehension
List1 = ["2,6,4,5", "3,7,4,2"]
Output = [','.join(sorted(lis)) for lis in [s.split(',') for s in List1]]
['2,4,5,6', '2,3,4,7']

Replace string in specific index in list of lists python

How can i replace a string in list of lists in python but i want to apply the changes only to the specific index and not affecting the other index, here some example:
mylist = [["test_one", "test_two"], ["test_one", "test_two"]]
i want to change the word "test" to "my" so the result would be only affecting the second index:
mylist = [["test_one", "my_two"], ["test_one", "my_two"]]
I can figure out how to change both of list but i can't figure out what I'm supposed to do if only change one specific index.
Use indexing:
newlist = []
for l in mylist:
l[1] = l[1].replace("test", "my")
newlist.append(l)
print(newlist)
Or oneliner if you always have two elements in the sublist:
newlist = [[i, j.replace("test", "my")] for i, j in mylist]
print(newlist)
Output:
[['test_one', 'my_two'], ['test_one', 'my_two']]
There is a way to do this on one line but it is not coming to me at the moment. Here is how to do it in two lines.
for two_word_list in mylist:
two_word_list[1] = two_word_list.replace("test", "my")

Extract substrings from a list into a list in Python

I have a Python list like:
['user#gmail.com', 'someone#hotmail.com'...]
And I want to extract only the strings after # into another list directly, such as:
mylist = ['gmail.com', 'hotmail.com'...]
Is it possible? split() doesn't seem to be working with lists.
This is my try:
for x in range(len(mylist)):
mylist[x].split("#",1)[1]
But it didn't give me a list of the output.
You're close, try these small tweaks:
Lists are iterables, which means its easier to use for-loops than you think:
for x in mylist:
#do something
Now, the thing you want to do is 1) split x at '#' and 2) add the result to another list.
#In order to add to another list you need to make another list
newlist = []
for x in mylist:
split_results = x.split('#')
# Now you have a tuple of the results of your split
# add the second item to the new list
newlist.append(split_results[1])
Once you understand that well, you can get fancy and use list comprehension:
newlist = [x.split('#')[1] for x in mylist]
That's my solution with nested for loops:
myl = ['user#gmail.com', 'someone#hotmail.com'...]
results = []
for element in myl:
for x in element:
if x == '#':
x = element.index('#')
results.append(element[x+1:])

How do I merge a 2D array in Python into one string with List Comprehension?

List Comprehension for me seems to be like the opaque block of granite that regular expressions are for me. I need pointers.
Say, I have a 2D list:
li = [[0,1,2],[3,4,5],[6,7,8]]
I would like to merge this either into one long list
li2 = [0,1,2,3,4,5,6,7,8]
or into a string with separators:
s = "0,1,2,3,4,5,6,7,8"
Really, I'd like to know how to do both.
Like so:
[ item for innerlist in outerlist for item in innerlist ]
Turning that directly into a string with separators:
','.join(str(item) for innerlist in outerlist for item in innerlist)
Yes, the order of 'for innerlist in outerlist' and 'for item in innerlist' is correct. Even though the "body" of the loop is at the start of the listcomp, the order of nested loops (and 'if' clauses) is still the same as when you would write the loop out:
for innerlist in outerlist:
for item in innerlist:
...
Try that:
li=[[0,1,2],[3,4,5],[6,7,8]]
li2 = [ y for x in li for y in x]
You can read it like this:
Give me the list of every ys.
The ys come from the xs.
The xs come from li.
To map that in a string:
','.join(map(str,li2))
There's a couple choices. First, you can just create a new list and add the contents of each list to it:
li2 = []
for sublist in li:
li2.extend(sublist)
Alternately, you can use the itertools module's chain function, which produces an iterable containing all the items in multiple iterables:
import itertools
li2 = list(itertools.chain(*li))
If you take this approach, you can produce the string without creating an intermediate list:
s = ",".join(itertools.chain(*li))
My favorite, and the shortest one, is this:
li2 = sum(li, [])
and
s = ','.join(li2)
EDIT: use sum instead of reduce, (thanks Thomas Wouters!)
For the second one, there is a built-in string method to do that :
>>> print ','.join(str(x) for x in li2)
"0,1,2,3,4,5,6,7,8"
For the first one, you can use join within a comprehension list :
>>> print ",".join([",".join(str(x) for x in li])
"0,1,2,3,4,5,6,7,8"
But it's easier to use itertools.flatten :
>>> import itertools
>>> print itertools.flatten(li)
[0,1,2,3,4,5,6,7,8]
>>> print ",".join(str(x) for x in itertools.flatten(li))
"0,1,2,3,4,5,6,7,8"
N.B : itertools is a module that help you to deal with common tasks with iterators such as list, tuples or string... It's handy because it does not store a copy of the structure you're working on but process the items one by one.
EDIT : funny, I am learning plenty of way to do it. Who said that there was only one good way to do it ?
import itertools
itertools.flatten( li )
To make it a flattened list use either:
http://code.activestate.com/recipes/121294/
http://code.activestate.com/recipes/363051/
Then, join to make it a string.
Here is a way:
def convert2DArrtostring(ndArr):
'''converts 2D array to string'''
arr_str = "["
for i in ndArr:
arr_str += "["
for j in i:
arr_str += str(j) + " "
arr_str += "]\n"
arr_str += "]"
return arr_str
There are many ways to do this problem. I like Numpy's tools because it is normally already imported in everything I do. However, if you aren't using Numpy for anything else this probably isn't a good method.
import numpy
li = [[0,1,2],[3,4,5],[6,7,8]]
li2=li[0] #first element of array to merge
i=1
while i<len(li):
li2=numpy.concatenate((li2,li[i]))
i+=1
print li2
This would print [0 1 2 3 4 5 6 7 8] and then you can convert this into your string too.

Categories