How to check dictionary for duplicate keys? [duplicate] - python

This question already has answers here:
Flag duplicate keys in dictionary using pylint
(2 answers)
Closed 14 days ago.
Python dictionaries cannot have duplicate keys, so something typed in like this:
chessSet = {'1b': 'wpawn', '1b': 'wking', '1c': 'wpawn'}
will be reduced to
chessSet = {'1b': 'wking', '1c': 'wpawn'}
How can I check and ensure the data entered into the dictionary does not have duplicate keys?
Overall, my goal would be an error message warning that this mistake was made.
Edit: more specifically, I am referring to trying to catch mistakes of typing this information into the source code. Is there a way to check if someone made a typo and created a second duplicate key which will overwrite the first one?

You need to if the key is already assigned and raise a warning.
chessSet = {'b1': 'wpawn', '1c':'wpawn'}
def move(piece, to):
if to in chessSet:
initial_piece = chessSet[to]
chessSet[to] = piece
print(f"{piece} has captured {initial_piece}")
else:
chessSet[to] = piece
Then you can try:
move('b1', 'wking')
And see what happens
Also:
move('b2', 'wking')

Related

Cannot loop over an array [duplicate]

This question already has an answer here:
Access specific information within worklogs in jira-python
(1 answer)
Closed 5 years ago.
I'm trying to insert the following worklog JSON fields that are part of an array using Python however I don't seem to be able to loop over an array in Python.
See code snippet below:
try:
worklogs_to_insert = []
for i in issue.fields.worklog["worklogs"]:
worklogs_to_insert.append(i)
except AttributeError as e:
log.info("Something went wrong when processing worklogs. :(")
log.info(e)
I am getting the following error when script is run:
Something went wrong when processing worklogs. :(
type object 'PropertyHolder' has no attribute 'worklog'
try using
for i in issue.fields.worklog.raw["worklogs"]

Loop through json file and delete key if it matches [duplicate]

This question already has answers here:
Is there a simple way to delete a list element by value?
(25 answers)
Closed 6 years ago.
I have the following structure on a JSON file:
{
"channels": [
"180873781382873088",
"181268808055521280",
"183484852287307777",
"174886257636147201",
"174521530573651968"
]
}
I want to know how I can loop through the file searching for a specific string, and delete it if it matches.
Thank you.
EDIT: A Google search pointed me to using a for loop and using the del command to remove the key, so here's what I tried:
channel = "180873781382873088"
for item in data['channels']:
del channel
But it only deletes the variable channel, not the key that matches it's value.
Try
data['channels'].remove(channel)
instead of the for loop.
This will automatically search the array and remove any key matching your variable. If you need help saving the results to a file I would open another question.

Removing items from a list in python following validity check [duplicate]

This question already has answers here:
How to remove items from a list while iterating?
(25 answers)
Closed 6 years ago.
Background:
I am writing a little script which requires, as one of it's arguments, an email address list in a file. The script will them go on to use the email address over a telnet connection to an SMTP server, so they need to be syntactically valid; consequently I have put a function to check the email address validity (incidentally, this regex may not be perfect, but is not the focus of the question, please bear with me. Will probably be loosened up):
def checkmailsyntax(email):
match = re.match('^[_a-z0-9-]+(\.[_a-z0-9-]+)*#[a-z0-9-]+(\.[a-z0-9-]+)*(\.[a-z]{2,4})$', email)
if match == None:
return True
The main() program goes on to read the input filename as an argument (in argparse) and insert it into a (currently global) list:
with open(args.targetfile) as targets:
target_email_list = targets.readlines()
I figured it would be great for the script to automatically delete an email address from the list (rather than just telling you it was wrong which is what it used to do) if the checkmailsyntax function failed. This cleaned list could then go on to submit syntactically valid email addresses to the SMTP server:
for i in target_email_list:
if checkmailsyntax(i):
target_email_list.remove(i)
Error checking code that I have put in both before and after the delete element snippet to see if it's doing it's job:
for i in target_email_list:
print i
The issue: The output of the code is thus:
Before delete element snippet (and the entire contents of the file submitted):
me#example.com
you#example.com
them#example.com
noemail.com
incorrectemail.com
new#example.com
pretendemail.com
wrongemail.com
right#example.com
badlywrong.com
whollycorrect#example.com
After delete element snippet:
me#example.com
you#example.com
them#example.com
incorrectemail.com
new#example.com
wrongemail.com
right#example.com
whollycorrect#example.com
So I'm pretty stumped as to why 'noemail.com', 'pretendemail.com' and 'badlywrong.com' were removed and yet 'incorrectemail.com' and 'wrongemail.com' are not. It seems to occur when there are two syntactically incorrect emails in the file sequentially.
Can anyone point me in the right direction?
It is because you are removing elements from the list while iterating over it:
for i in target_email_list:
if checkmailsyntax(i):
target_email_list.remove(i) # here
Since, following values are together:
pretendemail.com
wrongemail.com
Once you remove pretendemail.com email, the next one wrongemail.com shifts up and the iterator thinks that this has been iterated. So the item which comes next is right#example.com and wrongemail.com is never checked for valid syntax. You can just add print(i) before checking the syntax and see for yourself.
You can use list comprehension for this purpose:
valid_emails = [email for email in target_email_list if checkmailsyntax(email)]
AKS's answer has you covered: don't remove from the list that you are iterating over! For a quick-fix, you can remove from the actual list while iterating over a copy:
for i in target_email_list[:]: # iterates over the slice
if checkmailsyntax(i):
target_email_list.remove(i) # removes from actual list

Python: pass an item's value instead of it's name [duplicate]

This question already has answers here:
How to access (get or set) object attribute given string corresponding to name of that attribute
(3 answers)
Closed 8 years ago.
This has to be asked somewhere already, but I don't know the right words to find or frame it. So please bear with me.
This code fragment:
code = 'VegCode'
d = {}
codes = foo_func
for item in codes:
print item.code
Results in:
RuntimeError: Row: Field code does not exist
if I change it like this, it will work, but I don't want to hard code the variable name:
for item in codes:
print item.VegCode
How do I pass the value of code to the item object instead of it's name? (and please tell me what key words would have led to an answer!)
Use getattr: getattr(item, code)
Keywords: how to access object's attribute by its name

Replacing None object with a Null when parsing XML with Python and LXML [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Parsing blank XML tags with LXML and Python
Given the following XML file:
<Car>
<Color>Blue</Color>
<Make>Chevy</Make>
<Model/>
</Car>
and using the following code:
Car = element.xpath('//Root/Foo/Bar/Car/node()')
parsedCarData = [{field.tag: field.text for field in Car} for action in Car]
How can I replace key values of type None with a blank string so I can use parsed key values into a MySQL statement.
My Attempt - Thanks to Marcin
Using a turnary seemed to work
parsedCars = [{field.tag: field.text if isinstance(field.text,str) else '' for field in Cars} for action in Cars]
For my cases it has always evaluated as true.However when outputting a previous None type is outputs twice. Improvements are welcome!
Given your requirement, you might be better off filtering on is None, but in practice, I doubt this will make a difference:
parsedCars = [{field.tag: field.text if field.text is not None else '' for field in Cars} for action in Cars]
You should probably use basestr instead of str, though, because your code will replace all instances of unicode with '', should lxml ever switch to unicode.

Categories

Resources