(Newbie question) I want to write a Python program that removes a concrete item from a set if it is present in the set.
When the set is predefined, the code goes like this:
set = {1,2,3,4,4,5,6,10}
set.discard(4)
print(set)
What would be a way to write this, so that it applies to any set of values not known beforehand? I tried the following but it didnĀ“t work. Is there a method along those lines that does?
def set(items):
if i in items == 4:
set.discard(4)
else:
print("The number 4 is not in the set.")
print(set({1,2,4,6}))
This will discard the 4 in any set passed to the function:
def discard4(items):
if 4 in items:
items.discard(4)
return "Discarded"
else:
return "The number 4 is not in the set."
print(discard4({1,2,6})) # will print "The number 4 is not in the set."
print(discard4({1,2,4,6})) # will print "Discarded"
Related
I'm relatively new to python, and I can't figure out how to do this. I need to take a number input from a user, then turn that into an already existing variable. So far, I've managed to take the input, but I don't think I can make it into a variable. I am trying to turn this said input (number) to be added onto the back of a string (the string is pos)
So, for example, If I entered the number 1, i would have pos1, 2 would be pos2, so on.
if win == 0:
displayboard()
newPlot = input("")
postochange = "pos"+newPlot
if postochange == "X" or "O":
print ("Sorry, but that space is taken!")
else:
if playerTurn == 1:
postochange = "X"
else:
postochange = "O"
I'll try to simplify this some more, I want to have the user give me a number, that I add to the text "pos" and that corresponds to a variable that I already have.
Can you instead use a dictionary of values e.g.:
pos_s = {'pos1':None,
'pos2':None}
pos_s['pos'+str(user_number)] = desired_value
then to get the value of the variable you would do this:
pos_s.get('pos'+str(user_number), None)
just complementing Mason Caiby's answer, if the final user can only enter a finite collection of values, I would validate the entry with a set.
Then you can associate/correspond to a variable that you already have.
# Python program to demonstrate differences
# between normal and frozen set
# Same as {"a", "b","c"}
normal_set = set(["a", "b","c"])
# Adding an element to normal set is fine
normal_set.add("d")
print("Normal Set")
print(normal_set)
# A frozen set
frozen_set = frozenset(["e", "f", "g"])
print("Frozen Set")
print(frozen_set)
# Uncommenting below line would cause error as
# we are trying to add element to a frozen set
# frozen_set.add("h")
I'm trying to print out a list of nodes connected to other nodes so I can view them for debugging some python code revolving around graphs. I'm doing this for practice so I'm setting up nodes/edges/groups myself.
I've tried printing out the connections with my function inside of the myNode class using a for each type loop. But I get different output if I specify the index of the array and call the same method on it.
def print_connections(self):
for node in self.connections:
print(node.name, end = " ")
...
for node in nodes:
node.print_connections()
print(" ") # so I can have a newline in between groups
print(nodes[1].print_connections())
The for/each has good output, or appears to be good:
2 5 3 0
which differs from the line with the indexed print:
2 5 3 0 None
Is this expected behavior in python? How can I get around this?
your print_connections(self) doesn't return any value, thus return None, and what you're trying to do is with print(nodes[1].print_connections()) is to print the returned value by nodes[1].print_connections(), which is going to be None,
so what you should do instead is just,
for node in nodes:
node.print_connections()
print(" ")
nodes[1].print_connections()
I'm trying to display data from a csv in a text table. I've got to the point where it displays everything that I need, however the table width still has to be set, meaning if the data is longer than the number set then issues begin.
I currently print the table using .format to sort out formatting, is there a way to set the width of the data to a variable that is dependant on the length of the longest piece of data?
for i in range(len(list_l)):
if i == 0:
print(h_dashes)
print('{:^1s}{:^26s}{:^1s}{:^26s}{:^1s}{:^26s}{:^1s}{:^26s}{:^1s}'.format('|', (list_l[i][0].upper()),'|', (list_l[i][1].upper()),'|',(list_l[i][2].upper()),'|', (list_l[i][3].upper()),'|'))
print(h_dashes)
else:
print('{:^1s}{:^26s}{:^1s}{:^26s}{:^1s}{:^26s}{:^1s}{:^26s}{:^1s}'.format('|', list_l[i][0], '|', list_l[i][1], '|', list_l[i][2],'|', list_l[i][3],'|'))
I realise that the code is far from perfect, however I'm still a newbie so it's piecemeal from various tutorials
You can actually use a two-pass approach to first get the correct lengths. As per your example with four fields per line, the following shows the basic idea you can use.
What follows is an example of the two-pass approach, first to get the maximum lengths for each field, the other to do what you're currently doing (with the calculated rather than fixed lengths):
# Can set MINIMUM lengths here if desired, eg: lengths = [10, 0, 41, 7]
lengths = [0] * 4
fmtstr = None
for pass in range(2):
for i in range(len(list_l)):
if pass == 0:
# First pass sets lengths as per data.
for field in range(4):
lengths[field] = max(lengths[field], len(list_l[i][field])
else:
# Second pass prints the data.
# First, set format string if not yet set.
if fmtstr is None:
fmtstr = '|'
for item in lengths:
fmtstr += '{:^%ds}|' % (item)
# Now print item (and header stuff if first item).
if i == 0: print(h_dashes)
print(fmtstr.format(list_l[i][0].upper(), list_l[i][1].upper(), list_l[i][2].upper(), list_l[i][3].upper()))
if i == 0: print(h_dashes)
The construction of the format string is done the first time you process an item in pass two.
It does so by taking a collection like [31,41,59] and giving you the string:
|{:^31s}|{:^41s}|{:^59s}|
There's little point using all those {:^1s} format specifiers when the | is not actually a varying item - you may as well code it directly into the format string.
I've been write this practice program for while now, the whole purpose of the code is to get user input and generate passwords, everything almost works, but the replace statements are driving me nuts. Maybe one of you smart programmers can help me, because I'm kinda new to this whole field of programming. The issue is that replace statement only seems to work with the first char in Strng, but not the others one. The other funcs blower the last run first and then the middle one runs.
def Manip(Strng):
#Strng = 'jayjay'
print (Strng.replace('j','h',1))
#Displays: 'hayjay'
print (Strng.replace('j','h',4))
#Displays: 'hayhay'
return
def Add_nums(Strng):
Size=len(str(Strng))
Total_per = str(Strng).count('%')
# Get The % Spots Position, So they only get replaced with numbers during permutation
currnt_Pos = 0
per = [] # % position per for percent
rGen = ''
for i in str(Strng):
if i == str('%'):
per.append(currnt_Pos)
currnt_Pos+=1
for num,pos in zip(str(self.ints),per):
rGen = Strng.replace(str(Strng[pos]),str(num),4);
return rGen
for pos in AlphaB: # DataBase Of The Positions Of Alphabets
for letter in self.alphas: #letters in The User Inputs
GenPass=(self.forms.replace(self.forms[pos],letter,int(pos)))
# Not Fully Formatted yet; you got something like Cat%%%, so you can use another function to change % to nums
# And use the permutations function to generate other passwrds and then
# continue to the rest of this for loop which will generate something like cat222 or cat333
Add_nums(GenPass) # The Function That will add numbers to the Cat%%%
print (rGen);exit()
I'm writing a Python 3 script that does tabulation for forestry timber counts.
The workers will radio the species, diameter, and height in logs of each tree they mark to the computer operator. The computer operator will then enter a command such as this:
OAK 14 2
which signifies that the program should increment the count of Oak trees of fourteen inches in diameter and two logs in height.
However, the workers also sometimes call in more than one of the same type of tree at a time. So the program must also be able to handle this command:
OAK 16 1 2
which would signify that we're increasing the count by two.
The way I have the parser set up is thus:
key=cmdtup[0]+"_"+cmdtup[1]+"_"+cmdtup[2]
try:
trees[key]=int(trees[key])+int(cmdtup[3])
except KeyError:
trees[key]=int(cmdtup[3])
except IndexError:
trees[key]=int(trees[key])+1
If the program is commanded to store a tree it hasn't stored before, a KeyError will go off, and the handler will set the dict entry instead of increasing it. If the third parameter is omitted, an IndexError will be raised, and the handler will treat it as if the third parameter was 1.
Issues occur, however, if we're in both situations at once; the program hasn't heard of Oak trees yet, and the operator hasn't specified a count. KeyError goes off, but then generates an IndexError of its own, and Python doesn't like it when exceptions happen in exception handlers.
I suppose the easiest way would be to simply remove one or the other except and have its functionality be done in another way. I'd like to know if there's a more elegant, Pythonic way to do it, though. Is there?
I would do something like this:
def parse(cmd, trees):
res = cmd.split() # split the string by spaces, yielding a list of strings
if len(res) == 3: # if we got 3 parameters, set the fourth to 1
res.append(1)
for i in range(1,4): # convert parameters 1-3 to integers
res[i] = int(res[i])
key = tuple(res[x] for x in range(3)) # convert list to tuple, as lists cannot be dictionary indexes
trees[key] = trees.get(key,0) + res[3] # increase the number of entries, creating it if needed
trees={}
# test data
parse("OAK 14 2", trees)
parse("OAK 16 1 2", trees)
parse("OAK 14 2", trees)
parse("OAK 14 2", trees)
# print result
for tree in trees:
print(tree, "=", trees[tree])
yielding
('OAK', 16, 1) = 2
('OAK', 14, 2) = 3
Some notes:
no error handling here, you should handle the case when a value supposed to be a number isn't or the input is wrong in any other way
instead of strings, I use tuples as a dictionary index
You could use collections.Counter, which returns 0 rather than a KeyError if the key isn't in the dictionary.
Counter Documentation:
Counter objects have a dictionary interface except that they return a zero count for missing items instead of raising a KeyError
Something like this:
from collections import Counter
counts = Counter()
def update_counts(counts, cmd):
cmd_list = cmd.split()
if len(cmd_list) == 3:
tree = tuple(cmd_list)
n = 1
else:
*tree, n = tuple(cmd_list)
counts[tree] += n
Same notes apply as in uselpa's answer. Another nice thing with Counter is that if you want to, e.g., look at weekly counts, you just do something like sum(daily_counts).
Counter works even better if you're starting from a list of commands:
from collections import Counter
from itertools import repeat
raw_commands = get_commands() # perhaps read a file
command_lists = [c.split() for c in raw_commands]
counts = Counter(parse(command_lists))
def parse(commands):
for c in commands:
if len(c) == 3:
yield tuple(c)
elif len(c) == 4
yield from repeat(tuple(c[0:2]), times=c[3])
From there you can use the update_counts function above to add new trees, or you can start collecting the commands in another text file and then generate a second Counter object for the next day, the next week, etc.
In the end, the best way was to simply remove the IndexError handler, change cmdtup to a list, and insert the following:
if len(cmdtup) >= 3:
cmdtup.append(1)