I have a dictionary that contains strings as keys and lists as values.
I'd like to remove all list elements that contain the strings "food", "staging", "msatl" and "azeus". I have the below code already, but am having a hard time applying the logic I have in filterIP to the rest of the strings I have.
def filterIP(fullList):
regexIP = re.compile(r'\d{1,3}.\d{1,3}.\d{1,3}.\d{1,3}$')
return filter(lambda i: not regexIP.search(i), fullList)
groups = {key : [domain.replace('fake.com', 'env.fake.com')
for domain in filterIP(list(set(items)))]
for (key, items) in groups.iteritems() }
for key, value in groups.iteritems():
value.sort()
meta = { "_meta" : { "hostvars" : hostvars } }
groups.update(meta)
print(self.json_format_dict(groups, pretty=True))
Example of current output
"role_thumper": [
"thumper-msatl1-prod-1.env.fake.com",
"thumper-msatl1-prod-2.env.fake.com",
"thumper-rwva1-prod-1.env.fake.com",
"thumper-rwva1-prod-2.env.fake.com",
"thumper-rwva1-prod-3.env.fake.com",
"thumper-rwva1-prod-4.env.fake.com",
"thumper-rwva1-prod-5.env.fake.com",
"thumper-rwva1-prod-6.env.fake.com",
"thumper-staging-1.env.fake.com"
],
"role_thumper_mongo": [
"thumper-mongo-staging-1.env.fake.com",
"thumper-mongo-staging-2.env.fake.com",
"thumpermongo-rwva1-staging-1.env.fake.com",
"thumpermongo-rwva1-staging-2.env.fake.com"
],
"role_thumper_mongo_arb": [
"thumper-mongo-arb-staging-1.env.fake.com",
"thumpermongo-arb-rwva1-staging-1.env.fake.com"
],
A list comprehension is what you're after
x= ["a", "b", "aa", "aba"]
x_filtered = [i for i in x if "a" not in i]
print(x_filtered)
>>> ['b']
This is just shorthand for a for loop.
x_filtered = []
for i in x:
if "a" not in i:
x_filtered.append(i)
A simple way to accomplish your task would be to iterate over each lists in the dictionary. Create new lists based upon your criteria, and assign the new lists to the same keys but in a new dictionary. Here is how that would look like in code:
def filter_words(groups, words):
d = {}
for key, domains in groups.iteritems():
new_domains = []
for domain in domains:
if not any(word in domain for word in words):
new_domains.append(domain)
d[key] = new_domains
return d
And you would call it like so:
groups = filter_words(groups, {"food", "staging", "msatl" and "azeus"})
The "meat" of the code above is the second for loop:
for domain in domains:
if not any(word in domain for word in words):
new_domains.append(domain)
This code goes over each string in the current key's list, and filters out all invalid strings according to a list of invalid words.
If I understand you correctly, this might help.
Set up an exclude list:
exclude= ["food", "staging", "msatl", "azeus"]
Test list ( I couldn't really find instances in your examples)
test= ["food", "staging", "msatl", "azeus", "a", "bstaging"]
Run list comprehension (the name of iterators don't matter, you can pick more appropriate ones)
result= [i for i in test if not any([e for e in exclude if e in i])]
result
['a']
The answer above by #Julian gives a good explanation of what list comprehensions do. This uses two of them, the any part is True if there is any match in the exclude list.
Hope this helps.
Related
I have the following list and am wanting to convert it into a dictionary where the 4 digit value at the start of each item becomes the id.
['3574,A+,2021-03-24', '3575,O+,2021-04-03', '3576,AB-,2021-04-09', '3580,AB+,2021-04-27', '3589,A+,2021-05-08', '3590,B-,2021-05-11']
I have tried many different methods but it doesn't seem to work.
You can use str.split, map and dictionary comprehension
# data holds the list you have provided
{splitted[0]:splitted[1:] for splitted in map(lambda item:item.split(','), data)}
OUTPUT:
Out[35]:
{'3574': ['A+', '2021-03-24'],
'3575': ['O+', '2021-04-03'],
'3576': ['AB-', '2021-04-09'],
'3580': ['AB+', '2021-04-27'],
'3589': ['A+', '2021-05-08'],
'3590': ['B-', '2021-05-11']}
You can use dictionary comprehension with str.split:
lst = [
"3574,A+,2021-03-24",
"3575,O+,2021-04-03",
"3576,AB-,2021-04-09",
"3580,AB+,2021-04-27",
"3589,A+,2021-05-08",
"3590,B-,2021-05-11",
]
out = {int(v.split(",")[0]): v.split(",")[1:] for v in lst}
print(out)
Prints:
{
3574: ["A+", "2021-03-24"],
3575: ["O+", "2021-04-03"],
3576: ["AB-", "2021-04-09"],
3580: ["AB+", "2021-04-27"],
3589: ["A+", "2021-05-08"],
3590: ["B-", "2021-05-11"],
}
Here is the code to do what I believe you asked for. I have also added comments in the code for a bit more clarification.
my_list = ['3574,A+,2021-03-24',
'3575,O+,2021-04-03',
'3576,AB-,2021-04-09',
'3580,AB+,2021-04-27',
'3589,A+,2021-05-08',
'3590,B-,2021-05-11']#your list
my_dict = {}#The dictionary you want to put the list into
print("Your list:", my_list, "\n")
for item in my_list:#cycles through every item in your list
ID, value = item.split(",", 1)#Splits the item in your list only once (when it sees the first comma)
print(ID + ": " + value)
my_dict[ID] = value#Add the ID and value to your dictionary
print("\n" + "Your desired dictionary:", my_dict)
Which outputs this:
Your list: ['3574,A+,2021-03-24', '3575,O+,2021-04-03', '3576,AB-,2021-04-09', '3580,AB+,2021-04-27', '3589,A+,2021-05-08', '3590,B-,2021-05-11']
3574: A+,2021-03-24
3575: O+,2021-04-03
3576: AB-,2021-04-09
3580: AB+,2021-04-27
3589: A+,2021-05-08
3590: B-,2021-05-11
Your desired dictionary: {'3574': 'A+,2021-03-24', '3575': 'O+,2021-04-03', '3576': 'AB-,2021-04-09', '3580': 'AB+,2021-04-27', '3589': 'A+,2021-05-08', '3590': 'B-,2021-05-11'}
Enjoy!
TRY:
result = dict(i.split(',', 1) for i in lst)
OUTPUT:
{'3574': 'A+,2021-03-24',
'3575': 'O+,2021-04-03',
'3576': 'AB-,2021-04-09',
'3580': 'AB+,2021-04-27',
'3589': 'A+,2021-05-08',
'3590': 'B-,2021-05-11'}
I'm trying to merge data from 2 lists by an ID:
list_a = [
(u'65d92438497c', u'compute-0'),
(u'051df48db621', u'compute-4'),
(u'd6160db0cbcd', u'compute-3'),
(u'23fc20b59bd6', u'compute-1'),
(u'0db2e733520d', u'controller-1'),
(u'89334dac8a59', u'compute-2'),
(u'51cf9d50b02e', u'compute-5'),
(u'f4fe106eaeab', u'controller-2'),
(u'06cc124662dc', u'controller-0')
]
list_b = [
(u'65d92438497c', u'p06619'),
(u'051df48db621', u'p06618'),
(u'd6160db0cbcd', u'p06620'),
(u'23fc20b59bd6', u'p06622'),
(u'0db2e733520d', u'p06612'),
(u'89334dac8a59', u'p06621'),
(u'51cf9d50b02e', u'p06623'),
(u'f4fe106eaeab', u'p06611'),
(u'06cc124662dc', u'p06613')
]
list_ab = [
(u'65d92438497c', u'p06619', u'compute-0'),
(u'051df48db621', u'p06618', u'compute-4'),
(u'd6160db0cbcd', u'p06620', u'compute-3'),
(u'23fc20b59bd6', u'p06622', u'compute-1'),
(u'0db2e733520d', u'p06612', u'controller-1'),
(u'89334dac8a59', u'p06621', u'compute-2'),
(u'51cf9d50b02e', u'p06623', u'compute-5'),
(u'f4fe106eaeab', u'p06611', u'controller-2'),
(u'06cc124662dc', u'p06613', u'controller-0')
]
You can see that the first field in an ID, identical between list_a and list_b and I need to merge on this value
I'm not sure what type of data I need for result_ab
The purpose of this is to find 'compute-0' from 'p06619' so maybe there is a better way than merge.
You are using a one-dimensional list containing a tuple, it could be not needed. Anyway, to obtain the output you require:
list_a = [(u'65d92438497c', u'compute-0')]
list_b = [(u'65d92438497c', u'p-06619')]
result_ab = None
if list_a[0][0] == list_b[0][0]:
result_ab = [tuple(list(list_a[0]) + list(list_b[0][1:]))]
Here is my solution :
merge = []
for i in range(0,len(list_a)):
if list_a[i][0] == list_b[i][0]:
merge.append([tuple(list(list_a[i]) + list(list_b[i][1:]))])
The idea is to create a dictionary with the keys as the first element of both the lists and values as the list object with all the elements matching that key.
Next, just iterate over the dictionary and create the required new list object:
from collections import defaultdict
res = defaultdict(list)
for elt in list_a:
res[elt[0]].extend([el for el in elt[1:]])
for elt in list_b:
res[elt[0]].extend([el for el in elt[1:]])
list_ab = []
for key, value in res.items():
elt = tuple([key, *[val for val in value]])
list_ab.append(elt)
print(list_ab)
I have two lists. The first list has all the names.
firstList = ["mike", "mary", "steve", "jane"]
The second list contains the name I want to filter.
filteredList = ["mike", "mary"]
I want to exclude all names in the filtered list so that the final list looks like this:
finalList = ["steve","jane"]
The names are examples and the number of entries will vary and needs to be dynamic.
I started with this but it didn't run:
for b in firstList:
for s in filteredList:
finalList = firstList[firstList[b != s]]
print(finalList)
Thoughts? Any help would be appreciated.
Use numpy.setdiff1d
#import numpy as np
np.setdiff1d(firstList, filteredList).tolist()
or set with - operator
list(set(firstList) - set(filteredList))
or filter
list(filter(lambda x: x not in filteredList, firstList))
Output
['steve', 'jane']
You can use list comprehension to achieve this:
firstList = ["mike", "mary", "steve", "jane"]
filteredList = ["mike", "mary"]
finalList = [name for name in firstList if name not in filteredList]
# where `finalList` will hold: ['steve', 'jane']
Here you are iterating the firstList and checking the presence of each item in filteredList. If not present, consider it for your new list.
You can also use set() to achieve this as:
set(firstList) - set(filteredList)
# returns: set(['steve', 'jane'])
# if it is must for you to obtain the "finalList" as `list`,
# you can type-cast it as:
# finalList = list(set(firstList) - set(filteredList))
But via using set, you won't be able to preserve the order of these names in the firstList. And it will hold only unique items i.e. repetitive items will be removed. For example: if your "firstList" will contain ["mike", "mike", "mary", "steve", "jane"], finalList will just contain single "mike" whereas in the list comprehension based solution I proposed above, you'll see "mike" twice.
In the code you shared, it could be fixed as:
finalList = []
for b in firstList:
if b not in filteredList: # checking the presence of "b" in "filteredList"
finalList.append(b)
# where `finalList` will contain: ['steve', 'jane']
Can anyone help me figure the list comprehension way of producing following output -
Let given list be -
results = [
{"id": 1, "name": "input"},
{"name": "status", "desc": "Status"},
{"name": "entity", "fields": [
{"id": 101, "name": "value"},
{"id": 102, "name": "address"}]
}
]
And I am looking for output in the form of list.
The code to get the output is:
output = []
for eachDict in results:
if "fields" in eachDict:
for field in eachDict["fields"]:
output.append(eachDict["name"]+"."+field["name"])
else:
output.append(eachDict["name"])
Thus the output using above code is -
['input', 'status', 'entity.value', 'entity.address']
Is it possible to get similar output using if else nested for loops in list Comprehension?
I am having trouble trying to get access to that inner for loop in if condition of list Comprehension
My attempt -
output = [eachDict["name"]+"."+field["name"] for field in eachDict["fields"] if "fields" in eachDict else eachDict["name"] for eachDict in results]
One way to transform your code into workable code would be to make the inner loop produce lists, and then flatten the result afterward.
sum(([d['name'] + '.' + f['name'] for f in d['fields']]
if d.get('fields') else [d['name']] for d in results), [])
A list comprehension has a fixed number of (nested) loops. So must have two loops here, one over the top-level dictionaries, and one over the fields. The trick is to produce one iteration in the nested loop if there are no fields:
[d['name'] + fieldname
for d in results
for fieldname in (
('.' + sub['name'] for sub in d['fields']) if 'fields' in d else
('',))
]
The for fieldname loop loops either over the names of the fields sub-directories (with '.' prefixed), or over a tuple with just a single empty string in it.
Note that this isn't actually all that readable. I'd delegate producing the fieldname loop to a helper generator function to improve that:
def fieldnames(d):
if 'fields' in d:
for sub in d['fields']:
yield '.' + sub['name']
else:
yield ''
[d['name'] + fieldname for d in results for fieldname in fieldnames(d)]
Demo:
>>> def fieldnames(d):
... if 'fields' in d:
... for sub in d['fields']:
... yield '.' + sub['name']
... else:
... yield ''
...
>>> [d['name'] + fieldname for d in results for fieldname in fieldnames(d)]
['input', 'status', 'entity.value', 'entity.address']
I have a movietimes={}
It a dict I make by this code:
for i in Showtime.objects.filter(movie_id=movieid,theater_id=theaterid,datetime__range=(today,tomorrow))):
if i.mvtype not in movietimes:
movietimes[i.mvtype] = []
if not i.movietime > today :
movietimes[i.mvtype].append(i.movietime.strftime('%Y-%m-%dT%H:%M:%S.%fZ'))
if not movietimes : #this have bug
for i in Showtime.objects.filter(movie_id=movieid,datetime__range=(yesterday,today)):
if i.mvtype not in movietimes:
movietimes[i.mvtype] = []
movietimes[i.mvtype].append(i.movietime.strftime('%Y-%m-%dT%H:%M:%S.%fZ'))
return movietimes
result like this:
"Times": {
"ONE: [
"2014-12-24T10:40:00.000000Z",
"2014-12-24T12:45:00.000000Z",
"2014-12-25T14:50:00.000000Z"
]
}
I want to ask how can't I judge that if the [] in the 'ONE' part is null ??
I can't use if not movietimes={}: ,because there is u'ONE': [] in the dict
I have to judge the first list in the dict is empty . And there are many types u'ONE',u'TWO',u'Three'
they are catch by i.mvtype
{u'ONE': []}
{u'TWO': []}
{u'Three': []}
Please help me ,Thank you
if not movietimes["Times"]["ONE"]:
# you have empty list
That is presuming by first you mean the key ONE as dicts are not ordered
If you want to see if there is any empty list and your dict is like below:
movietimes = {"Times":{"ONE":[2],"TWO":[]}}
for val in movietimes["Times"].itervalues():
if not any(x for x in val):
# you have empty list