Python iterate through list and re-split items into list - python

I have a list that with items that I would like to split again and add as new items in the list. For example given the below list:
pre_songs = ['Totem', 'One, Two, Three', 'Rent', 'Vapors', 'Get Loud > Inspire Strikes Back',
'Enceladus', 'Moon Socket', 'Out of This World > Scheme', 'Walk to the Light',
'When The Dust Settles', 'Click Lang Echo']
I would like to take the "Get Loud > Inspire Strikes Back", and the "Out of This World > Scheme" Item and split them by the ">" and make "Get Loud", "Inspire Strikes Back", "Out of This World", and "Scheme" as separate items in the list.
I tried using the code below but it doesn't work:
pre_setlist = []
for song in pre_songs:
if song.contains('>'):
pre_setlist.append(song.split('>'))
else:
pre_setlist.append(song)

Use extend:
pre_setlist = []
for song in pre_songs:
pre_setlist.extend([x.strip() for x in song.split('>')])
Shorter, if there is always one space before and after the >:
pre_setlist = []
for song in pre_songs:
pre_setlist.extend(song.split(' > '))
Result for both version with your example list:
>>> pre_setlist
['Totem',
'One, Two, Three',
'Rent',
'Vapors',
'Get Loud',
'Inspire Strikes Back',
'Enceladus',
'Moon Socket',
'Out of This World',
'Scheme',
'Walk to the Light',
'When The Dust Settles',
'Click Lang Echo']

This is one way.
from itertools import chain
pre_setlist = []
for song in pre_songs:
if '>' in song:
pre_setlist.append(song.split(' > '))
else:
pre_setlist.append([song])
list(chain.from_iterable(pre_setlist))
# ['Totem', 'One, Two, Three', 'Rent', 'Vapors', 'Get Loud',
# 'Inspire Strikes Back', 'Enceladus', 'Moon Socket',
# 'Out of This World', 'Scheme', 'Walk to the Light',
# 'When The Dust Settles', 'Click Lang Echo']
This can be written more succinctly as a list comprehension:
from itertools import chain
pre_setlist = [[song] if '>' not in song \
else song.split(' > ') for song in pre_songs]
list(chain.from_iterable(pre_setlist))

You can try this:
pre_songs = ['Totem', 'One, Two, Three', 'Rent', 'Vapors', 'Get Loud > Inspire Strikes Back',
'Enceladus', 'Moon Socket', 'Out of This World > Scheme', 'Walk to the Light',
'When The Dust Settles', 'Click Lang Echo']
final_songs = [i for b in [c.split(' > ') for c in pre_songs] for i in b]
Output:
['Totem', 'One, Two, Three', 'Rent', 'Vapors', 'Get Loud', 'Inspire Strikes Back', 'Enceladus', 'Moon Socket', 'Out of This World', 'Scheme', 'Walk to the Light', 'When The Dust Settles', 'Click Lang Echo']

for song in pre_songs:
if '>' in song:
pre_setlist.extend(song.split('>'))
else:
pre_setlist.append(song)
You need to change 2 things
'>' in song instead of song.contains('>').
Use extend instead of append, since song.split gives you a list back

Related

Tkinter python 3.8 comboboxes in loop. How correct wrong choice while appending to list?

I´ve created a loop of comboboxes and I'm appending the choices I make to a list. There are 3 comboboxes. The list must have 3 corresponding elements. The problem is that if I change my mind while choosing and replace the option, the list (of course) increases in size.
In this code I have 3 options: 'The One!', 'more or less','the bad'. I want to change the options during selection, but keeping the list always with 3 unique elements corresponding to number of combobox. I've tought about using set but didn't work because the actual loop is large.
I need the list with just the len of comboboxes with result corresponding to the last choices, independently of the number of choice changes I've done.
Thank you for any help.
from tkinter import ttk
from tkinter import Tk
from tkinter import Button
root = Tk()
my_heroes = ['Zidane', 'Ronaldo', 'Messi']
position = ['The One!', 'more or less','the bad']
result =[]
def get_combo_choice(event, cmb):
result.append(cmb.get())
print(result)
for index, heroe in enumerate(my_heroes):
var = StringVar()
bestPlayers = ttk.Combobox(root,values=position, textvariable=var, state="readonly")
bestPlayers.grid(row=0 + index, column=1,padx=(15,25))
label = Label(root, text = heroe)
label.grid(row=0 + index, column=0,padx=(15,25))
bestPlayers.bind("<<ComboboxSelected>>",lambda event, cmb=var:get_combo_choice(event, cmb))
button = Button(root, text ="get list of choices", command = callback)
button.grid(row=4, column=0,padx=(15,25))
root.mainloop()
The print grows to three, ok, but then continues...
I need to keep size of list = combobox len and freely update the values getting the last 3 choices at the end.
['The One!']
['The One!', 'more or less']
['The One!', 'more or less', 'the bad']
['The One!', 'more or less', 'the bad', 'The One!']
['The One!', 'more or less', 'the bad', 'The One!', 'more or less']
['The One!', 'more or less', 'the bad', 'The One!', 'more or less', 'The One!']
['The One!', 'more or less', 'the bad', 'The One!', 'more or less', 'The One!', 'more or less']
['The One!', 'more or less', 'the bad', 'The One!', 'more or less', 'The One!', 'more or less', 'more or less']
You can limit list length by usng list slice.
def get_combo_choice(event, cmb):
global result
result.append(cmb.get())
# limit list len to 3 using ~2
result = result[~2:]
print(result)
In order to control result columns a few things need to be added to your code.
result =[None, None, None]
best = []
# Here's the alternative
def get_combo_choice(event, cmb):
i = best.index(event.widget)
result[i] = cmb.get()
print(result)
Inside the for\loop insert best.append(bestPlayers)
Mr Derek
I updated my code with your answer. It works like a charm!! You teached me a lot, big thanks!
import tkinter as tk
from tkinter import ttk
from tkinter import Tk
from tkinter import Button
root = Tk()
my_heroes = ['Zidane', 'Ronaldo', 'Messi']
position = ['The One!', 'more or less','the bad']
# result =[]
# def get_combo_choice(event, cmb):
# result.append(cmb.get())
# print(result)
result =[None, None, None]
best = []
# Here's the alternative
def get_combo_choice(event, cmb):
i = best.index(event.widget)
result[i] = cmb.get()
print(result)
for index, heroe in enumerate(my_heroes):
var = tk.StringVar()
bestPlayers = ttk.Combobox(root,values=position, textvariable=var, state="readonly")
best.append(bestPlayers)
bestPlayers.grid(row=0 + index, column=1,padx=(15,25))
label = tk.Label(root, text = heroe)
label.grid(row=0 + index, column=0,padx=(15,25))
bestPlayers.bind("<<ComboboxSelected>>",lambda event, cmb=var:get_combo_choice(event, cmb))
button = tk.Button(root, text ="get list of choices", command = get_combo_choice)
button.grid(row=4, column=0,padx=(15,25))
root.mainloop()
code results in :
['The One!', None, None]
['The One!', None, None]
['The One!', None, None]
['The One!', 'more or less', None]
['The One!', 'more or less', 'the bad']
One last question:
in: def get_combo_choice(event, cmb):
I understand event(choice--> ex:"the one"),
cbm (--> the variable) and that results uses the index to get choice from best(list),
what I dont understand is why I can't use i = best.index() if best is a list we already know. What is (event.widget) and what it is doing there? By the way your code fits all my needs.

Pickling a scraped list with BS4 vs Preset Data issue (why is it not working the same?)

I am trying to save this scraped data to file (pickle it) but I cannot figure out why I cannot pickle it with this code:
url = "https://www.imdb.com/list/ls016522954/?ref_=nv_tvv_dvd"
req = Request(url, headers={'User-Agent': 'Mozilla/5.0'})
web_byte = urlopen(req).read()
webpage = web_byte.decode('utf-8')
html_soup = BeautifulSoup(webpage, 'html5lib')
dvdNames = html_soup.find_all("div", class_="lister-item-content")
for dvd in dvdNames:
dvdArray.append(dvd.a.string)
viewtitles = input("Finished!, do you want to view the DVD titles? (Y/N): ")
if viewtitles == "y".casefold():
num = 1
for name in dvdArray:
print(""+ str(num) + " - " + name)
num += 1
elif viewtitles == "n".casefold():
print("Not Showing TItles!")
else:
print("that is not an option!")
saveToFile = input("Do you want to save / update the data? (Y/N): ")
if saveToFile == "y".casefold():
with open("IMDBDVDNames.dat", "wb") as f:
pickle.dump(dvdArray, f)
continue
elif saveToFile == "n".casefold():
print("Data Not Saved!")
continue
else:
print("That's not one of the option!")
continue
I've tried adding the sys.setrecursionlimit(1000000) and it doesn't make a difference (FYI) and am getting this error "maximum recursion depth exceeded while pickling an object" but when I run this code:
import pickle
testarray = []
if input("1 or 2?: ") == "1":
testarray = ['1917', 'Onward', 'The Hunt', 'The Invisible Man', 'Human Capital', 'Dolittle', 'Birds of Prey: And the Fantabulous Emancipation of One Harley Quinn', 'The Gentlemen', 'Bloodshot', 'The Way Back', 'Clemency', 'The Grudge', 'I Still Believe', 'The Song of Names', 'Treadstone', 'Vivarium', 'Star Wars: Episode IX - The Rise of Skywalker', 'The Current War', 'Downhill', 'The Call of the Wild', 'Resistance', 'Banana Split', 'Bad Boys for Life', 'Sonic the Hedgehog', 'Mr. Robot', 'The Purge', 'VFW', 'The Other Lamb', 'Slay the Dragon', 'Clover', 'Lazy Susan', 'Rogue Warfare: The Hunt', 'Like a Boss', 'Little Women', 'Cats', 'Madam Secretary', 'Escape from Pretoria', 'The Cold Blue', 'The Night Clerk', 'Same Boat', 'The 420 Movie: Mary & Jane', 'Manou the Swift', 'Gold Dust', 'Sea Fever', 'Miles Davis: Birth of the Cool', 'The Lost Husband', 'Stray Dolls', 'Mortal Kombat Legends: Scorpions Revenge', 'Just Mercy', 'The Righteous Gemstones', 'Criminal Minds', 'Underwater', 'Final Kill', 'Green Rush', 'Butt Boy', 'The Quarry', 'Abe', 'Bad Therapy', 'Yip Man 4', 'The Last Full Measure', 'Looking for Alaska', 'The Turning', 'True History of the Kelly Gang', 'To the Stars', 'Robert the Bruce', 'Papa, sdokhni', 'The Rhythm Section', 'Arrow', 'The Assistant', 'Guns Akimbo', 'The Dark Red', 'Dreamkatcher', 'Fantasy Island', 'The Etruscan Smile', "A Nun's Curse", 'Allagash']
with open("test.dat", "wb") as f:
pickle.dump(testarray, f)
else:
with open("test.dat", "rb") as f:
testarray = pickle.load(f)
print(testarray)
with the exact same (at least I hope it's the same, I did a print(dvdArray) and got the list that way FYI) information but it WILL let me pickle it when i do it like that
can someone let me know why and how I can fix it?
I know I'm scraping the data from a website and converting it into a list but cannot figure out what is causing the error in example 1 vs example 2
any help would be appreciated
Thanks,
lttlejiver
In Case anyone is curious, I added "strip()" to when I was appending the dvdArray and it worked!
dvdArray.append(dvd.a.string.strip())
BeautifulSoup objects are highly recursive, and so are very difficult to pickle. When you do dvdArray.append(dvd.a.string), dvd.a.string is not a python string, but a bs4.element.NavigableString - one of these complex objects. By using strip(), you're actually converting the bs4.element.NavigableString to a python string, which is easily pickled. The same would be true if you used dvd.a.getText().
For future reference, when pickling, always remember to convert (where possible) BeautifulSoup objects to simpler python objects.

Why isn't this if statement returning True?

I'm making a program that counts how many times a band has played a song from a webpage of all their setlists. I have grabbed the webpage and converted all the songs played into one big list so all I wanted to do was see if the song name was in the list and add to a counter but it isn't working and I can't seem to figure out why.
I've tried using the count function instead and that didn't work
sugaree_counter = 0
link = 'https://www.cs.cmu.edu/~mleone/gdead/dead-sets/' + year + '/' + month+ '-' + day + '-' + year + '.txt'
page = requests.get(link)
page_text = page.text
page_list = [page_text.split('\n')]
print(page_list)
This code returns the list:
[['Winterland Arena, San Francisco, CA (1/2/72)', '', "Truckin'", 'Sugaree',
'Mr. Charlie', 'Beat it on Down the Line', 'Loser', 'Jack Straw',
'Chinatown Shuffle', 'Your Love At Home', 'Tennessee Jed', 'El Paso',
'You Win Again', 'Big Railroad Blues', 'Mexicali Blues',
'Playing in the Band', 'Next Time You See Me', 'Brown Eyed Women',
'Casey Jones', '', "Good Lovin'", 'China Cat Sunflower', 'I Know You Rider',
"Good Lovin'", 'Ramble On Rose', 'Sugar Magnolia', 'Not Fade Away',
"Goin' Down the Road Feeling Bad", 'Not Fade Away', '',
'One More Saturday Night', '', '']]
But when I do:
sugaree_counter = int(sugaree_counter)
if 'Sugaree' in page_list:
sugaree_counter += 1
print(str(sugaree_counter))
It will always be zero.
It should add 1 to that because 'Sugaree' is in that list
Your page_list is a list of lists, so you need two for loops to get the pages, you need to do
for page in page_list:
for item in page:
sugaree_counter += 1
Use sum() and list expressions:
sugaree_counter = sum([page.count('Sugaree') for page in page_list])

how to concat on element to other in same list based on condition

I have a list of items : eg:
a = ['when', '#i am here','#go and get it', '#life is hell', 'who', '#i am here','#go and get it',]
I want to merge the list items based on condition i.e merge all the items till the item has # in first place and replace it with when or who. The output I want is :
['when', 'when i am here','when go and get it', 'when life is hell', 'who', 'who i am here','who go and get it',]
You can iterate over a, save the word if it does not start with'#', or replace '#' with the saved word if it does:
for i, s in enumerate(a):
if s.startswith('#'):
a[i] = p + s[1:]
else:
p = s + ' '
a becomes:
['when', 'when i am here', 'when go and get it', 'when life is hell', 'who', 'who i am here', 'who go and get it']
Just going off the info you provided, you could do this.
a = ['when', '#i am here','#go and get it', '#life is hell', 'who', '#i am here','#go and get it']
whoWhen = "" #are we adding 'who or when'
output = [] #new list
for i in a: #loop through
if " " not in i: #if there's only 1 word
whoWhen = i + " " #specify we will use that word
output.append(i.upper()) #put it in the list
else:
output.append(i.replace("#", whoWhen)) #replace hashtag with word
print(output)
Prints:
['WHEN', 'when i am here', 'when go and get it', 'when life is hell', 'WHO', 'who i am here', 'who go and get it']
Process returned 0 (0x0) execution time : 0.062 s
Press any key to continue . . .
Here you go:
def carry_concat(string_list):
replacement = "" # current replacement string ("when" or "who" or whatever)
replaced_list = [] # the new list
for value in string_list:
if value[0] == "#":
# add string with replacement
replaced_list.append(replacement + " " + value[1:])
else:
# set this string as the future replacement value
replacement = value
# add string without replacement
replaced_list.append(value)
return replaced_list
a = ['when', '#i am here','#go and get it', '#life is hell', 'who', '#i am here','#go and get it',]
print(a)
print(carry_concat(a))
This prints:
['when', '#i am here', '#go and get it', '#life is hell', 'who', '#i am here', '#go and get it']
['when', 'when i am here', 'when go and get it', 'when life is hell', 'who', 'who i am here', 'who go and get it']

Adding symbols to json Python

I was getting from website a json with tags.
['adventure in the comments', 'artist:s.guri', 'clothes', 'comments locked down', 'dashie slippers', 'edit', 'fractal', 'no pony', 'recursion', 'safe', 'simple background', 'slippers', 'tanks for the memories', 'the ride never ends', 'transparent background', 'vector', 'wat', 'we need to go deeper']
And i want to print it more or less like that
#adventureinthecomments #artist:s.guri #clothes #commentslockeddown #dashie #slippers #edit #fractal #nopony #recursion
Does somebody knows what method i need to use to remove all comas an add hashtag before word?
P.S Using Python 3
One of the ways is to join to the single string with '#' and strip all white spaces and replace '#' with ' #' (with space)
arr = ['adventure in the comments', 'artist:s.guri', 'clothes', 'comments locked down', 'dashie slippers', 'edit', 'fractal', 'no pony', 'recursion', 'safe', 'simple background', 'slippers', 'tanks for the memories', 'the ride never ends', 'transparent background', 'vector', 'wat', 'we need to go deeper']
s= "#"
res = '#' + s.join(arr)
newVal = res.replace(' ','')
newNew = newVal.replace('#', ' #')
print(newNew)
What's the rule for split the original sentences?, because the first one looks like
'adventure in the comments' = '#adventureinthecomments'
but
'comments locked down' is splitted to #comments #locked #down
?
If there is no rules this could works
>>> jsontags = ['adventure in the comments', 'artist:s.guri', 'clothes', 'comments locked down', 'dashie slippers', 'edit', 'fractal', 'no pony', 'recursion', 'safe', 'simple background', 'slippers', 'tanks for the memories', 'the ride never ends', 'transparent background', 'vector', 'wat', 'we need to go deeper']
>>> '#'+' #'.join([tag.replace(' ','') for tag in jsontags])
This will be the result
'#adventureinthecomments #artist:s.guri #clothes #commentslockeddown #dashieslippers #edit #fractal #nopony #recursion #safe #simplebackground #slippers #tanksforthememories #therideneverends #transparentbackground #vector #wat #weneedtogodeeper'

Categories