I have a list of strings:
ignore_list = ["new job", "encountered error", "SLA"]
and a list of dictionaries:
ticket_list =
[{"Title": "new job to action", "Level": "2", "url":"www.example.com"},
{"Title": "job SLA not met", "Level": "4", "url":"www.blabla.com"},
{"Title": "precheck failure", "Level": "1", "url":"www.halp.com"},
{"Title": "is anyone there", "Level": "1", "url":"www.hello.com"},
{"Title": "please update ticket", "Level": "4", "url":"www.asdfadf.com"},
{"Title": "provision assistance", "Level": "2", "url":"www.test.com"},
{"Title": "encountered error on job", "Level": "2", "url":"www.lkjlkj.com"}]
I am attempting to iterate through the ignore_list
as well as the ticket_list
and if any of the ignore_list
strings DO NOT exist within the dictionary key ['Title']. Append them to a new list.
action_tickets_list = []
for string in ignore_list:
for ticket in ticket_list:
if string not in ticket['Title']:
action_tickets_list.append(ticket)
print(action_tickets_list)
Whats happening is my action_tickets_list
is getting duplicates for each iteration through my ignore_list
.
Is there preferred or best practice to iterate over a list of strings and check to see if they exist within a specific dictionary key (in this case the ['Title']
key)? I have a feeling that using in
or not in
isn't an ideal solution?
My goal is to have action_tickets_list
to contain dictionaries that do not have the ignore_list
strings in the title key.
This has been stumping me for a while now and have had no luck finding a solution - Any help is greatly appreciated. The above code is just pseudo code of what I currently have, but I hope it's enough to understand my goal. Thanks in advance
CodePudding user response:
Another option is to replace your ignore_list
iterator with any()
and generator expression.
For example, using a set comprehension:
action_tickets_list = set(ticket['Title'] for ticket in ticket_list if not any(s in ticket['Title'] for s in ignore_list))
It's similar to
action_tickets_list = set()
for ticket in ticket_list:
if not any(s in ticket['Title'] for s in ignore_list):
action_tickets_list.add(ticket['Title'])
If you have a large ignore_list, it's probably worth compiling a regular expression of ignore_list. That means you only scan once.
import re
ignore = re.compile('|'.join(ignore_list))
action_tickets_list = set()
for ticket in ticket_list:
if not ignore.search(ticket['Title']):
action_tickets_list.add(ticket['Title'])
CodePudding user response:
For every element in ignore_list
, check every element in ticket_list
; if ticket_list['Title']
does not contain the element in ignore_list
, add it to action_tickets_list
.
So, then, for every element in ignore_list
, we have every element in ticket_list
, hence why you see duplicates.
The correct ordering should be as follows:
action_tickets_list = []
for ticket in ticket_list:
if not any(map(lambda ignore: ignore in ticket['Title'], ignore_list)):
action_tickets_list.append(ticket)
print(action_tickets_list)
CodePudding user response:
Looking at the code you provided,
action_tickets_list = []
for string in ignore_list:
for ticket in ticket_list:
if string not in ticket['Title']:
action_tickets_list.append(ticket)
print(action_tickets_list)
The line
action_tickets_list.append(ticket)
Is called every time one of the strings in ignore_list is not present in the “Title” slot of the dictionary checked. This will result in duplicate entries if a “Title” string does not contain more of the strings in the ignore_list.
If your goal is to include the dictionary if any one entry from the ignore list is not present in the dictionary’s “Title” string, you could iterate over the list of dictionaries in the outer loop and iterate over the strings in the inner loop, setting a Boolean value if any one of the strings is not present.
action_tickets_list = []
for ticket in ticket_list:
include = false
for str in ignore_list:
if str not in ticket:
include = true
if include:
action_ticket_list.append(ticket)
This solution might fix your problem.
It might also make sense to make your tickets into a user defined Ticket class with member variables for each entry instead of using dictionaries. It might improve readability and make it easier to avoid bugs down the line.
This class might look something like this
class Ticket:
def __init__(self, title, level, url):
self.title = title
self.level = level
self.url = url