how to loop over each changeInfo['changeInfo'][1...x]['Url'] - python

I have the following code snippet ,i want to change it in such a way where I want loop over for each changeInfo['changeInfo'][1..x],how can I do that
for changeInfo in MainchangeInfo:
if (changeInfo['CRStatus'] == 'Fix' and (('Not Provided' in changeInfo['changeInfo'][0]['Url'] or 'Wrong change Provided' in changeInfo['changeInfo'][0]['Url']) or 'NEW' in changeInfo['changeInfo'][0]['Status'] or 'ABANDONED' in changeInfo['changeInfo'][0]['Status'] or 'Yes' not in changeInfo['RNotesStatus'] or 'Provided' not in changeInfo['RCAInfo'] or 'False' in str(changeInfo['IsDevComplete']))):
if 'Wrong change Provided' in changeInfo['changeInfo'][0]['Url'] or changeInfo['changeInfo'][0]['Info'] != 'Available' ://want to loop over for changeInfo['changeInfo'][0]
changeMailBody = changeMailBody + "<tr bgcolor=\"Red\">"

what do you mean by [1..x]?
if you want to loop over the 'first x' elements in changeInfo['changeInfo'] (in which case, did you mean [0..x]?) you can use slice notation:
for item in changeInfo['changeInfo'][:x]:
# do stuff
if you really want from 1 to x, i.e. skipping the first element you can do:
for item in changeInfo['changeInfo'][1:x]:
# do stuff
See docs here:
http://docs.python.org/2.3/whatsnew/section-slices.html
EDIT:
After your clarification in the comment it's clear you don't even need slice notation, you just need for item in changeInfo['changeInfo'] ...I think your full example would look like:
for changeInfo in MainchangeInfo:
for item in changeInfo['changeInfo']:
if (changeInfo['CRStatus'] == 'Fix' and (('Not Provided' in item['Url'] or 'Wrong change Provided' in item['Url']) or 'NEW' in item['Status'] or 'ABANDONED' in item['Status'] or 'Yes' not in changeInfo['RNotesStatus'] or 'Provided' not in changeInfo['RCAInfo'] or 'False' in str(changeInfo['IsDevComplete']))):
if 'Wrong change Provided' in item['Url'] or item['Info'] != 'Available' ://want to loop over for changeInfo['changeInfo'][0]
changeMailBody = changeMailBody + "<tr bgcolor=\"Red\">"

You can do this with an explicit loop:
for change in changeInfo['changeInfo']:
info = change['info']
# do stuff with it
Or, if you want to write it out as a comprehension:
infos = [change['info'] for change in changeInfo['changeInfo']]
Or, if you just want an iterator, not a list:
infos = (change['info'] for change in changeInfo['changeInfo'])
In any case, you will get changeInfo['changeInfo'][0]['info'], then changeInfo['changeInfo'][1]['info'], and so on.
I'm assuming here that changeInfo['changeInfo'] is a list, not a dict whose keys happen to be small integers. If that assumption is wrong, just replace changeInfo['changeInfo'] with changeInfo['changeInfo'].values() in whichever solution you choose. (Of course in that case, the order will be arbitrary, but that's exactly what you should expect from a dict.)
So, in your existing code, instead of this:
if ('Wrong change Provided' in changeInfo['changeInfo'][0]['Url'] or
changeInfo['changeInfo'][0]['Info'] != 'Available'):
… I'd use the generator expression, together with the any function, like this:
if any('Wrong change Provided' in change['Url'] or change['Info'] != 'Available'
for change in changeInfo['changeInfo']):
Now instead of checking whether this condition is true for the first value in changeInfo['changeInfo']—that is, changeInfo['changeInfo'][0]—you're testing whether it's true for any of the values in changeInfo['changeInfo']. Which, as I understand it, is exactly what you wanted.

Related

How to check if ANY key in dict is empty? Python

I am iterating over a spreadsheet (specifically google sheets) and it returns a list of dictionaries.
I am able to access each dict by using ...
sheet = client.open('test').sheet1
list = sheet.get_all_records()
for row in list:
In each dictionary, I need to run a function that checks to see if a specific key is empty, if it is then it returns that dictionary that contains the empty key. I am able to do this by using ...
for row in list:
if bool(row['name']) == False:
print(row)
My question is how would I check to see if ANY dictionary has the key 'name' empty, if no dict has the key 'name' empty, run a command?
Hope this made sense.
You can use the any function to check the entire collection:
if any([bool(r['name']) == False for r in list]):
print('at least one')
#Mad Physicist made a good point that is worth examining.
In Python, variable values can be converted to boolean and evaluated based on their 'truthiness'. If using the bool function to convert a value, '', None, 0, and False all convert to False. Any other value converts to True.
The same conversion happens when using not. bool(x)==False is the same as not x
With this in mind, you can make the code more concise:
if any([not r['name'] for r in list]):
print('at least one')
As #MP also mentioned, you can reverse the logic using all:
if not all([r['name'] for r in list]):
print('at least one')
all will implicitly convert each value to a boolean
On a side note, don't use list as a variable name since it is a type in Python.
If I understood correctly, I like
empty = filter(
lambda row: not row[“name”],
my_list
)
if len(empty):
return empty
# do stuff

Python3: for-loop break and else (if statement)

Background information:
hey,
I want to do the following: I have a dictionary with IDs as keys and lists with various things as value. One of the items of the value is a string. I want to check, if a list contains this string. And I want to do it for all keys in my dictionary.
If the list contains the string, I want to print "String is valid"
If the list does not contain the string, I want to print "String is NOT valid"
So far, so good.
Furthermore, the lists I want to check depend on one console input of the user, which specifies, which list should be checked. The console input is "number".
My idea was to iterate over my dictionary and my list with a nested for-loop and compare, if the string(the item of the value) is equal to any list item. If it is, I want to break out of the loop. If the String is not found in the list, I want to execute the else-statement to print my "String is not valid" message.
Code snippet:
def validationHelper(myDict, myList):
for key in myDict:
for value in myDict[key][0]:
for item in myList:
if value==item:
validationHelper.true="String is valid"
break
else:
validationHelper.true="Warning: String is NOT valid"
def validation(anyList,helperfunc):
if anyList=="one":
return helperfunc(finalDict,myList1)
if anyList=="two":
return helperfunc(finalDict,myList2)
if anyList=="three":
return helperfunc(finalDict,myList3)
validation(number, validationHelper)
print(validationHelper.true)
Problem:
I am running this, but no matter if the string is in the list or not, I always get my printout for the else-statement. So, I guess I have an error in reasoning in my for-loop? Or maybe, I did not understand for-loops at all?! I have tried out different indentions with the else-statement, but couldnt solve my problem.
I would suggest you to change your function the following way (without changing the logic):
def validationHelper(myDict, myList):
for key in myDict:
for value in myDict[key][0]:
for item in myList:
if value==item:
return "String is valid" # Add here to exit
return "Warning: String is NOT valid" # will be returned inf nothing will be found in your 3 loops
def validation(anyList,helperfunc):
if anyList=="one":
return helperfunc(finalDict,myList1)
if anyList=="two":
return helperfunc(finalDict,myList2)
if anyList=="three":
return helperfunc(finalDict,myList3)
validation(number, validationHelper)
print(validationHelper)
This will help you to exit your 3 nested loops as it was mentioned in comments.
Because in the negative case on first wrong occurrence you don't need to check anything else.
Use return to break all of your loop. Having an else statement is not necessary if you don't have any if statement to begin with.
def validationHelper(myDict, myList):
for item in myList:
if item in myDict.values():
return ("String is valid")
return ("String is NOT valid")
def validation(anyList,helperfunc):
if anyList=="one":
return helperfunc(finalDict,myList1)
elif anyList=="two":
return helperfunc(finalDict,myList2)
elif anyList=="three":
return helperfunc(finalDict,myList3)
validation(number, validationHelper)
print(validationHelper.true)
Using elif instead of multiple if is a better practice. Be careful with indentions next time.
Also you might want to check .keys() and .values()
You can replace:
for key in myDict:
for value in myDict[key][0]:
with:
for value in myDict.values():
The other answers give a good explanation of how to break out of multiple loops. But you could also simplify your code by using Python's built-in functions and list comprehensions, like this:
def validationHelper(myDict, myList):
if any(v in myList for val in myDict.values() for v in val[0]):
validationHelper.true="String is valid"
else:
validationHelper.true="Warning: String is NOT valid"
def validation(anyList,helperfunc):
if anyList=="one":
return helperfunc(finalDict,myList1)
if anyList=="two":
return helperfunc(finalDict,myList2)
if anyList=="three":
return helperfunc(finalDict,myList3)
validation(number, validationHelper)
print(validationHelper.true)
This should be as efficient as your code, since any short circuits at the first match. And it may be a little more readable. (Note that multi-level list comprehensions go in the same order as regular for loops.)

Python oneline foreach verification in string

I want to be sure that none item of a list is present on a string.
At the moment I do :
presents = False
for item in item_list:
if item in string_control:
presents = True
break;
Is there a way to do it in only one line ? I really often do these types of control.
Yes :
presents = any(x in string_control for x in item_list)
I think string_control has a value something like this. presents then becomes a boolean indicating the same as in your code but most likely in most circumstances you don't need the cast to bool. I.e. this probably works fine too: presents = [i for i in item_list if i == string_control]
string_control = None
presents = bool([i for i in item_list if i == string_control])

Should I return an empty dict instead of None?

I have a method that currently returns None or a dict.
result,error = o.apply('grammar')
The caller currently has to check for the existence of two keys to decide what kind of object was returned.
if 'imperial' in result:
# yay
elif 'west' in result:
# yahoo
else:
# something wrong?
Because result can be None, I'm thinking of returning an empty dict instead, so the caller does not need to check for that. What do you think ?
For comparison, in the re module, the result of calling match can result in None.
p = re.compile('\w+')
m = p.match( 'whatever' )
But in this case, m is an object instance. In my case, I am returning a dict which should either be empty or have some entries.
Yes I think returning an empty dict (or where applicable an empty list) is preferable to returning None as this avoids an additional check in the client code.
EDIT:
Adding some code sample to elaborate:
def result_none(choice):
mydict = {}
if choice == 'a':
mydict['x'] = 100
mydict['y'] = 1000
return mydict
else:
return None
def result_dict(choice):
mydict = {}
if choice == 'a':
mydict['x'] = 100
mydict['y'] = 1000
return mydict
test_dict = result_dict('b')
if test_dict.get('x'):
print 'Got x'
else:
print 'No x'
test_none = result_none('b')
if test_none.get('x'):
print 'Got x'
else:
print 'No x'
In the above code the check test_none.get(x) throws an AttributeError as
result_none method can possibly return a None. To avoid that I have to add an
additional check and might rewrite that line as:
if test_none is not None and test_none.get('x') which is not at all needed
if the method were returning an empty dict. As the example shows the check test_dict.get('x') works fine as the method result_dict returns an empty dict.
I'm not entirely sure of the context of this code, but I'd say returning None suggests that there was somehow an error and the operation could not be completed. Returning an empty dictionary suggests success, but nothing matched the criteria for being added to the dictionary.
I come from a completely different background (C++ Game Development) so take this for what it's worth:
For performance reasons though, might be nice to return None and save whatever overhead, though minimal, may be involved in creating an empty dictionary. I find that, generally, if you're using a scripting language, you're not concerned about the performance of that code. If you were, you probably wouldn't be writing that feature in said language unless required for some unavoidable reason.
As others have said, an empty dict is falsy, so there's no problem there. But the idea of returning an empty dict leaves a bad taste in my mouth. I can't help but feel that returning an empty dict could hide errors that returning None would reveal. Still, it's just a gut feeling.
After more thought, I think returning an empty dict might be more Pythonic. A good rule of thumb might be to always return an empty container if you write a function/method which returns a container. Several examples of this behavior:
"".split() == []
filter(lambda a:False, [1,2]) == []
range(1, -1) == []
re.findall('x', '') = []
In contrast if you are trying to get a single object, you have no choice but to return None I suppose. So I guess None is like the empty container for single objects! Thanks to KennyTM for arguing some sense into me :D
Python supports returning multiple values. Hence, you can return a status of success along with an empty dictionary. The caller first verifies the return code and then uses the dictionary.
def result_none(choice):
mydict = {}
retcode = -1
if choice == 'a':
mydict['x'] = 100
mydict['y'] = 1000
retcode = 0
return mydict, retcode
retcode, mydict = result_none('a')
if retcode == 0:
<<use dictionary>>

Do I have to cause an ValueError in Python

I have this code:
chars = #some list
try:
indx = chars.index(chars)
except ValueError:
#doSomething
else:
#doSomethingElse
I want to be able to do this because I don't like knowfully causing Exceptions:
chars = #some list
indx = chars.index(chars)
if indx == -1:
#doSomething
else:
#doSomethingElse
Is there a way I can do this?
Note that the latter approach is going against the generally accepted "pythonic" philosophy of EAFP, or "It is Easier to Ask for Forgiveness than Permission.", while the former follows it.
if element in mylist:
index = mylist.index(element)
# ... do something
else:
# ... do something else
For the specific case where your list is a sequence of single-character strings you can get what you want by changing the list to be searched to a string in advance (eg. ''.join(chars)).
You can then use the .find() method, which does work as you want. However, there's no corresponding method for lists or tuples.
Another possible option is to use a dictionary instead. eg.
d = dict((x, loc) for (loc,x) in enumerate(chars))
...
index = d.get(chars_to_find, -1) # Second argument is default if not found.
This may also perform better if you're doing a lot of searches on the list. If it's just a single search on a throwaway list though, its not worth doing.

Categories