Common part of two lists - python-3.x

list_1 is generated each time new
list_2 is unchangeable
In window is printed list_1 in default black colour and i want to make red numbers if they occur in list_2
import tkinter as tk
from tkinter import Label
from random import randint
list_1 = [randint(1, 100) for i in range(12)]
list_2 = [2, 5, 8, 9, 14, 26, 28, 34, 43, 51, 55, 60, 77]
root = tk.Tk()
label = tk.Label(root, text=list_1, padx=15, pady=15)
label.pack()
root.mainloop()
I've tried like this:
if list_2 in list_1:
label.config(fg='red')
or this:
for i in list_2:
for i in list_1:
label.config(fg='red')
But nothing works. Where is mistake?

To check for common hashable items in lists you may want to use sets:
if set(list_2) & set(list_1):
label.config(fg='red')
Or
if any(n in set(list_2) for n in list_1):
label.config(fg='red')
You can also use any and a generator expression:
if any(n in list_2 for n in list_1):
label.config(fg='red')
But its slower and less pythonic.

Related

How can I have a slideshow with matplotlib graphs in tkinter?

I would like to utilize a tkinter window with integrated matplotlib graphs that cycle every x seconds. However, this is what I have and I am stuck. Any help would be greatly appreciated. Thank you!
import time
import matplotlib.pyplot as plt
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
import tkinter as tk
root = tk.Tk()
root.geometry('500x500')
x = [1, 2, 3, 4, 5]
y = [[3, 6, 1, 9, 2], [2, 0, 1, 4, 6], [6, 3, 8, 2, 0]]
fig = plt.figure(figsize=(5,5))
i = 0
while i < len(y):
plt.plot(x, y[i])
canvas = FigureCanvasTkAgg(fig, master=root)
canvas.draw()
canvas.get_tk_widget().pack()
time.sleep(1)
plt.clf()
i += 1
root.mainloop()
What you're looking for is after(). You'll likely have an easier time if you wrap everything up in a simple Root class, so I've done that here.
# imports go here as usual...
class Root(tk.Tk):
def __init__(self):
super().__init__() # init tk.Tk()
self.geometry('500x500')
self.x = [1, 2, 3, 4, 5]
self.y = [[3, 6, 1, 9, 2], [2, 0, 1, 4, 6], [6, 3, 8, 2, 0]]
self.fig = plt.figure(figsize=(5, 5))
# set up the canvas
self.canvas = FigureCanvasTkAgg(fig, master=root)
self.canvas.get_tk_widget().pack()
# begin cycling plots, starting with index 0
self.index = 0
self.cycle_plots(self.index)
def cycle_plots(self, index):
plt.clf # clear plot here
self.index += 1 # go to the next index
if self.index >= len(self.y):
self.index = 0 # wrap around
plt.plot(self.x, self.y[self.index])
self.canvas.draw() # update the canvas
# after 1000mS, call this function again
self.after(1000, lambda i=self.index: self.cycle_plots(i))
if __name__ == '__main__': # run the app!
root = Root()
root.mainloop()
Using a class makes it easier to pass your UI objects - like the Canvas - around between functions (methods). Here, self refers to your Root class, so anything inside it can share variables with self.<varname>, like self.canvas

DataFrame display not as expected

I tried to color the title of the columns in purple, but what I got from the output doesn't seem aligned. Is there a way to fix it?
import pandas as pd
purple_text = '\033[35m'
reset = '\033[m'
list_1 = [12, 27, 33, 56, 11, 90]
list_2 = [43, 55, 76, 26, 84, 62]
df = pd.DataFrame({f'{purple_text} Numbers_1 {reset}': list_1,
f'{purple_text} Numbers_2 {reset}': list_2})
print(df.to_string(index=False))
Your issue comes from the fact that this formatting is making header text an incorrect size.
In order to remedy this, you should use display settings, this one works fine:
pd.set_option('display.colheader_justify', 'left')
Results:
Aligned

Two similar scripts creating different lists

I have two python scripts.
Here's the first:
def testListOutput():
myCount=1
myList=[[[x for x in range(3)] for y in range(3)] for z in range(3)]
for i in range(3):
for j in range(3):
for k in range(3):
myList[i][j][k]=myCount
myCount+=1
print(myList)
It produces the following output in the console: "[[[1, 2, 3], [4, 5, 6], [7, 8, 9]], [[10, 11, 12], [13, 14, 15], [16, 17, 18]], [[19, 20, 21], [22, 23, 24], [25, 26, 27]]]"
That's what I was expecting. Here's the second:
def tryDifferentWay():
myCount=1
myList=[x for x in range(3)]
for m in range(2):
myList=[myList for x in range(3)]
for i in range(3):
for j in range(3):
for k in range(3):
myList[i][j][k]=myCount
myCount+=1
print(myList)
Output: [[[25, 26, 27], [25, 26, 27], [25, 26, 27]], [[25, 26, 27], [25, 26, 27], [25, 26, 27]], [[25, 26, 27], [25, 26, 27], [25, 26, 27]]]
Why is the output not the same?
Thanks for your help.
Alright, lets look at the two different ways you built up myList:
OPTION 1:
myList=[[[x for x in range(3)] for y in range(3)] for z in range(3)]
OPTION 2:
myList=[x for x in range(3)]
for m in range(2):
myList=[myList for x in range(3)]
So, in option 1 everything goes as you expect, a 3x3x3 grid of individual values is initialized to 0, 1 or 2 thanks to your lovely list comprehension.
In option 2, the first line creates a length 3 list and assigns that to myList I will call this length 3 list my3List. Then your first pass through the for loop will reassign myList to be [my3List,my3List,my3List].
Note that all 3 of those variables point to the same place, the object my3List that was created in the first line. So changing any one of these values will necessairly change the others, because they all point to the same place. The next pass through the for loop just does this again until you have a 3x3 list of the my3List object.
Essentially option 1 makes a 3x3x3 list of individual values, option 2 creates a 3x3 list of references to the exact same length 3 list.

How to generate a random number in a list from a range

I have a dice program, and i have this:
import random
if how_much == "32":
dice_32 = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32]
print(dice_32)
How i can made this shorter, to the list generates a number from 1 to 32 ( or bigger ) without making the list even bigger?
You can generate a random integer between two endpoints in Python with the random.randint() function. This spans the full [x, y] interval and may include both endpoints:
>>> random.randint(0, 10)
7
>>> random.randint(500, 50000)
18601
With random.randrange(), you can exclude the right-hand side of the interval, meaning the generated number always lies within [x, y] and will always be smaller than the right endpoint:
>>> random.randrange(1, 10)
5
If you need to generate random floats that lie within a specific [x, y] interval, you can use random.uniform(), which plucks from the continuous uniform distribution:
>>> random.uniform(20, 30)
27.42639687016509
>>> random.uniform(30, 40)
36.33865802745107
To pick a random element from a non-empty sequence (like a list or a tuple), you can use random.choice(). There is also random.choices() for choosing multiple elements from a sequence with replacement (duplicates are possible):
>>> items = ['one', 'two', 'three', 'four', 'five']
>>> random.choice(items)
'four'
>>> import random
>>> random.randint(1,32)
22
>>> random.randint(1,35)
17
>>> random.randint(1,100)
10
>>> random.randint(1,100)
100
>>> random.randint(1,100)
81
>>> random.randrange(1,100)
91
>>> random.choice(range(100))
60
>>> random.choice(range(100))
55
>>> random.choice(range(100))
58

Iterating through a list and outputting it through create_text

I'm having some trouble with tkinter's create_text. I'm trying to iterate through a list and have create_text output each item in the list one by one. I can't figure this out, as every time I've tried, it does not work the way I want it to. Here's some code that exemplifies the issue:
class GUI(Frame):
def __init__(self, master):
self.test_list = [1, 2, 3, 4, 5, 6, 7, 8, 9]
self.c = Canvas(master, width=300, height=300)
self.c.pack()
for items in self.test_list:
items = items
for i in range(0, 300, 100):
for j in range(0, 300, 100):
self.c.create_text(j + 25, i + 20, text=items)
root = Tk()
root.title("Test")
root.geometry("300x300")
GUI(root)
mainloop()
Thank you and I appreciate the help.
Your code had severe indentation problems.
Further, you did not call mainloop on any object.
Then, the position of the objects on the canvas was outside the visible window:
I fixed the code so it runs, and displays something on the canvas; from there, you can modify it to suit your needs.
import tkinter as tk
class GUI(tk.Frame):
def __init__(self, master):
self.test_list = [1, 2, 3, 4, 5, 6, 7, 8, 9]
self.c = tk.Canvas(master, width=300, height=300)
self.c.pack()
for idx, elt in enumerate(self.test_list):
row = (idx // 3 + 5) * 20
col = (idx % 3 + 5) * 20
self.c.create_text(row, col, text=elt)
if __name__ == '__main__':
root = tk.Tk()
root.title("Test")
root.geometry("300x300")
GUI(root)
root.mainloop()
This has two outer loops.
# iterates, items == 9 now
for items in self.test_list:
items = items
# uses 9 over and over
for i in range(0, 300, 100):
for j in range(0, 300, 100):
self.c.create_text(j + 25, i + 20, text=items)
Maybe try this instead.
for items in self.test_list:
for i in range(0, 300, 100):
for j in range(0, 300, 100):
self.c.create_text(j + 25, i + 20, text=items)

Resources