Related
I am trying to split a list every 5th item, then delete the next two items ('nan'). I have attempted to use List[:5], but that does not seem to work in a loop. The desired output is: [['1','2','3','4','5'],['1','2','3','4','5'],['1','2','3','4','5'],['1','2','3','4','5']]
List = ['1','2','3','4','5','nan','nan','1','2','3','4','5','nan','nan','1','2','3','4','5','nan','nan','1','2','3','4','5','nan','nan']
for i in List:
# split first 5 items
# delete next two items
# Desired output:
# [['1','2','3','4','5'],['1','2','3','4','5'],['1','2','3','4','5'],['1','2','3','4','5']]
There are lots of ways to do this. I recommend stepping by 7 then splicing by 5.
data = ['1','2','3','4','5','nan','nan','1','2','3','4','5','nan','nan','1','2','3','4','5','nan','nan','1','2','3','4','5','nan','nan']
# Step by 7 and keep the first 5
chunks = [data[i:i+5] for i in range(0, len(data), 7)]
print(*chunks, sep='\n')
Output:
['1', '2', '3', '4', '5']
['1', '2', '3', '4', '5']
['1', '2', '3', '4', '5']
['1', '2', '3', '4', '5']
Reference: Split a python list into other “sublists”...
WARNING: make sure the list follows the rules as you said, after every 5 items 2 nan.
This loop will add the first 5 items as a list, and delete the first 7 items.
lst = ['1','2','3','4','5','nan','nan','1','2','3','4','5','nan','nan','1','2','3','4','5','nan','nan','1','2','3','4','5','nan','nan']
output = []
while True:
if len(lst) <= 0:
break
output.append(lst[:5])
del lst[:7]
print(output) # [['1', '2', '3', '4', '5'], ['1', '2', '3', '4', '5'], ['1', '2', '3', '4', '5'], ['1', '2', '3', '4', '5']]
List=['1','2','3','4','5','nan','nan','1','2','3','4','5','nan','nan','1','2','3','4','5','nan','nan','1','2','3','4','5','nan','nan']
new_list = list()
for k in range(len(List)//7):
new_list.append(List[k*7:k*7+5])
new_list.append(List[-len(List)%7])
Straightforward solution in case if the list doesn’t follow the rules you mentioned but you want to split sequence always between NAN's:
result, temp = [], []
for item in lst:
if item != 'nan':
temp.append(item)
elif temp:
result.append(list(temp))
temp = []
Using itertools.groupby would also support chunks of different lengths:
[list(v) for k, v in groupby(List, key='nan'.__ne__) if k]
I guess there is more pythonic way to do the same but:
result = []
while (len(List) > 5):
result.append(List[0:0+5])
del List[0:0+5]
del List[0:2]
This results: [['1', '2', '3', '4', '5'], ['1', '2', '3', '4', '5'], ['1', '2', '3', '4', '5'], ['1', '2', '3', '4', '5']]
mainlist=[]
sublist=[]
count=0
for i in List:
if i!="nan" :
if count==4:
# delete next two items
mainlist.append(sublist)
count=0
sublist=[]
else:
# split first 5 items
sublist.append(i)
count+=1
Generally numpy.split(...) will do any kind of custom splitting for you. Some reference:
https://docs.scipy.org/doc/numpy/reference/generated/numpy.split.html
And the code:
import numpy as np
lst = ['1','2','3','4','5','nan','nan','1','2','3','4','5','nan','nan','1','2','3','4','5','nan','nan','1','2','3','4','5','nan','nan']
ind=np.ravel([[i*7+5, (i+1)*7] for i in range(len(lst)//7)])
lst2=np.split(lst, ind)[:-1:2]
print(lst2)
Outputs:
[array(['1', '2', '3', '4', '5'], dtype='<U3'), array(['1', '2', '3', '4', '5'], dtype='<U3'), array(['1', '2', '3', '4', '5'], dtype='<U3'), array(['1', '2', '3', '4', '5'], dtype='<U3')]
I like the splice answers.
Here is my 2 cents.
# changed var name away from var type
myList = ['1','2','3','4','5','nan','nan','1','2','3','4','10','nan','nan','1','2','3','4','15','nan','nan','1','2','3','4','20','nan','nan']
newList = [] # declare new list of lists to create
addItem = [] # declare temp list
myIndex = 0 # declare temp counting variable
for i in myList:
myIndex +=1
if myIndex==6:
nothing = 0 #do nothing
elif myIndex==7: #add sub list to new list and reset variables
if len(addItem)>0:
newList.append(list(addItem))
addItem=[]
myIndex = 0
else:
addItem.append(i)
#output
print(newList)
User provides input with spaces:
row = list(input())
print(row)
['1','2','3',' ','4','5','6',' ','7','8','9',' ']
So I need to create 'row' list into the below. The list is divided into sub-lists based on whitespace:
[['1','2','3'],['4','5','6'],['7','8','9']]
You can use str.split to split by whitespace:
myinput = '123 456 789'
row = list(map(list, myinput.split()))
print(row)
[['1', '2', '3'], ['4', '5', '6'], ['7', '8', '9']]
Alternatively, using a list comprehension:
row = [list(i) for i in myinput.split()]
You can usestr.split to split the input on spaces to give a list of sub-strings.
E.g. '123 456 789' would become ['123', '456', '789'].
Then use a list-comprehension to convert these strings into lists of characters with the list() constructor (as you are already familiar with).
Making the final code:
row = [list(s) for s in input().split()]
#[['1', '2', '3'], ['4', '5', '6'], ['7', '8', '9']]
Starting with your list rather than the string, you can do that using itetools.groupby:
from itertools import groupby
row = ['1','2','3',' ','4','5','6',' ','7','8','9',' ']
out = [list(group) for key, group in groupby(row, lambda x: x != ' ') if key]
print(out)
# [['1', '2', '3'], ['4', '5', '6'], ['7', '8', '9']]
We group the values depending on whether or not they are spaces, and only keep the groups that are not made of spaces.
Try this:
abc=['1','2','3',' ','4','5','6',' ','7','8','9',' ']
newList=list()
temp=list()
for i in abc:
if(i==' '):
newList.append(temp)
temp=list()
else:
temp.append(i)
print(newList)
Output:
[['1', '2', '3'], ['4', '5', '6'], ['7', '8', '9']]
I'd like to turn
[1,2,3,4,5,4,3,2,1]
into
['1','2','3','4','5','4','3','2','1']
in preparation of doing FreqDist.
Use the built-in map function when casting each item in the list:
newList = map(str, oldList)
Just use a simple list comprehension
>>> myar=[1,2,3,4,5,4,3,2,1]
>>> [str(i) for i in myar]
['1', '2', '3', '4', '5', '4', '3', '2', '1']
I have a string array, for example:
a = ['123', '456', '789']
I want to split it to form a 2-dimension char array:
b = [['1', '2', '3'], ['4', '5', '6'], ['7', '8', '9']]
I'm using
[[element for element in line] for line in array]
to achieve my goal but found it not easy to read, is there any built-in function or any readable way to do it?
Looks like a job for map:
>>> a = ['123', '456', '789']
>>> map(list, a)
[['1', '2', '3'], ['4', '5', '6'], ['7', '8', '9']]
Relevant documentation:
map
list
you could do something like:
first_list = ['123', '456', '789']
other_weirder_list = [list(line) for line in first_list]
Your solution isn't that bad, but you might do something like this or the map suggestion by arashajii.
map(list, array) should do it.
You can use map:
>>> a
['123', '456', '789']
>>> map(list, a)
[['1', '2', '3'], ['4', '5', '6'], ['7', '8', '9']]
Although I really don't see why you'd need to do this (unless you plan on editing one specific character in the string?). Strings behave similarly to lists.
First I tried e.split(''), but I get ValueError: empty separator.
Try this:
a = ['123', '456', '789']
b = [list(e) for e in a]
b
[['1', '2', '3'], ['4', '5', '6'], ['7', '8', '9']]
This is quite complicated but i would like to be able to refresh a larger list once at item has been taken out of a mini list within the bigger list.
listA = ['1','2','3','4','5','6','6','8','9','5','3','7']
i used the code below to split it into lists of threes
split = [listA[i:(i+3)] for i in range(0, len(listA) - 1, 3)]
print(split)
# [['1','2','3'],['4','5','6'],['6','8','9'],['5','3','7']]
split = [['1','2','3'],['4','5','6'],['6','8','9'],['5','3','7']]
if i deleted #3 from the first list, split will now be
del split[0][-1]
split = [['1','2'],['4','5','6'],['6','8','9'],['5','3','7']]
after #3 has been deleted, i would like to be able to refresh the list so that it looks like;
split = [['1','2','4'],['5','6','6'],['8','9','5'],['3','7']]
thanks in advance
Not sure how big this list is getting, but you would need to flatten it and recalculate it:
>>> listA = ['1','2','3','4','5','6','6','8','9','5','3','7']
>>> split = [listA[i:(i+3)] for i in range(0, len(listA) - 1, 3)]
>>> split
[['1', '2', '3'], ['4', '5', '6'], ['6', '8', '9'], ['5', '3', '7']]
>>> del split[0][-1]
>>> split
[['1', '2'], ['4', '5', '6'], ['6', '8', '9'], ['5', '3', '7']]
>>> listA = sum(split, []) # <- flatten split list back to 1 level
>>> listA
['1', '2', '4', '5', '6', '6', '8', '9', '5', '3', '7']
>>> split = [listA[i:(i+3)] for i in range(0, len(listA) - 1, 3)]
>>> split
[['1', '2', '4'], ['5', '6', '6'], ['8', '9', '5'], ['3', '7']]
Just recreate the single list from your nested lists, then re-split.
You can join the lists, assuming they are only one level deep, with something like:
rejoined = [element for sublist in split for element in sublist]
There are no doubt fancier ways, or single-liners that use itertools or some other library, but don't overthink it. If you're only talking about a few hundred or even a few thousand items this solution is quite good enough.
I need this for turning of cards in the deck in a solitaire game.
You can deal your cards using itertools.groupby() with a good key function:
def group_key(x, n=3, flag=[0], counter=itertools.count(0)):
if next(counter) % n == 0:
flag[0] = flag[0] ^ 1
return flag[0]
^ is a bitwise operator, basically it change the value of the flag from 0 to 1 and viceversa. The flag value is an element of a list because we're doing some kind of memoization.
Example:
>>> deck = ['1', '2', '3', '4', '5', '6', '6', '8', '9', '5', '3', '7']
>>> for k,g in itertools.groupby(deck, key=group_key):
... print(list(g))
['1', '2', '3']
['4', '5', '6']
['6', '8', '9']
['5', '3', '7']
Now let's say you've used card '9' and '8', so your new deck looks like:
>>> deck = ['1', '2', '3', '4', '5', '6', '6', '5', '3', '7']
>>> for k,g in itertools.groupby(deck, key=group_key):
... print(list(g))
['1', '2', '3']
['4', '5', '6']
['6', '5', '3']
['7']
Build an object that contains a list and tracks when the list is altered (probably by controlling write to it), then have the object do it's own split every time the data is altered and save the split list to a member of the object.