Home > Software design >  list of strings exist within a list of dict keys?
list of strings exist within a list of dict keys?

Time:05-15

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
  • Related