Dictionary key name from combination of string and variable value - python

Basically, I am trying to append values from a list as key-value pairs to a new dictionary. I want the key names in a specific format and order.
#!/usr/bin/env python3
ipv4_list = ["192.168.1.2", "192.168.1.3", "192.168.1.4"]
ipv4_dic = {}
ipv4_len = len(ipv4_list)
i = 1
for val in range(len(ipv4_list)):
ipv4_dic[i] = ipv4_list[val]
i+=1
print(ipv4_dic)
Current output:
{1: '192.168.1.2', 2: '192.168.1.3', 3: '192.168.1.4'}
The above is good but I want to change key names to something like IP1, IP2, etc.
How do I make that in the line ipv4_dic[i] = ipv4_list[key]
I tried something like ipv4_dic["IP"+i] but does not work.
ipv4_dic["IP"+i] = ipv4_list[val]
TypeError: can only concatenate str (not "int") to str
The expected dictionary output as follows:
{IP1: '192.168.1.2', IP2: '192.168.1.3', IP3: '192.168.1.4'}

It does not work because you are trying to concatenate a string with an integer, which is not allowed in Python.
In order to have your code working with the minimum possible amendments is to transform the integer i to a string, via the str() function, i.e. replacing in your code
ipv4_dic["IP"+i] = ipv4_list[val]
with
ipv4_dic["IP"+str(i)] = ipv4_list[val]
However, you can use dict comprehension, i.e. you loop each position of the ipv4_dic you're about to create, placing there a key built from each element of your ipv4_list, in a single line of code.
ipv4_list = ["192.168.1.2", "192.168.1.3", "192.168.1.4"]
ipv4_dic = {f"IP{i+1}": ipv4_list[i] for i in range(len(ipv4_list))}
Explanation:
for each i in the range from 0 to len(ipv4_list) we are building the single dictionary key through an f-string, concatenating the string "IP" to the value i+1 (the range starts at 0, but you want your first dict element to be "IP1", that's why i+1). Then, we set the value for this key as ipv4_list[i], which are the single elements contained in your starting list.
The basic usage is
l = ['A', 'B', 'C']
d = {i : l[i] for i in range(len(l))}
which is pretty similar to your case, without the refinements in the keys creation, since you're incrementing the index (i.e. i) and concatenating it to a string.

Use a dictionary comprehension with enumerate starting a 1:
ipv4_list = ["192.168.1.2", "192.168.1.3", "192.168.1.4"]
ipv4_dic = {f'IP{n}':ip for n,ip in enumerate(ipv4_list,1)}
print(ipv4_dic)
{'IP1': '192.168.1.2', 'IP2': '192.168.1.3', 'IP3': '192.168.1.4'}

ipv4_list = ["192.168.1.2", "192.168.1.3", "192.168.1.4"]
ipv4_dict= {}
# enumerate will give you the index and value of the iterator
# f-string can compute the value inside the {} and format it like a string
for index,value in enumerate(ipv4_list):
ipv4_dict[f"IP{index+1}"] = value
# or
ipv4_dict_1 = {f"IP{index+1}": value for index,value in enumerate(ipv4_list)}
# out:
print(ipv4_dict)
# {'IP1': '192.168.1.2', 'IP2': '192.168.1.3', 'IP3': '192.168.1.4'}
print(ipv4_dict_1)
# {'IP1': '192.168.1.2', 'IP2': '192.168.1.3', 'IP3': '192.168.1.4'}

I almost didn’t post this because Georgio almost had what I would have written: use a dictionary comprehension based on a for loop. Andd tell you about the str and int concatenation.
The only thing missing was using enumerate to get the list indices. Full of goodness, is enumerate. It returns the elements from an iterable as a list of pairs (tuples): first item is the zero-based index, second is what the for loop (well actually the iterable at that index) would normally return.
Then those pairs get assigned to i,v via tuple unpacking.
di = { f"IP{i+1}":v for i,v in enumerate( [" 192.168.1.2", "192.168.1.3", "192.168.1.4"])}
print(di)
See https://docs.python.org/3/library/functions.html#enumerate

Dictionaries work like this:
thisdict = {
"brand": "Ford",
"model": "Mustang",
"year": 1964
}
Try this:
ipv4_list = ["192.168.1.2", "192.168.1.3", "192.168.1.4"]
ipv4_dic = {}
ipv4_len = len(ipv4_list)
i = 1
for key in range(len(ipv4_list)):
auxStr = "IP" + str(i) #convert i to string, and merging IP
ipv4_dic[auxStr] = ipv4_list[key]
i+=1
print(ipv4_dic)
This should do it!
Happy coding!!!

Related

Converting a list with multiple values into a dictionary

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'}

Dictionary initialization syntax

def __init__(self, devices, queue):
'''
'''
self.devices = devices
self.queue = queue
values = {k:0 for k in devices.keys()}
values[0xbeef] = len(values) # the number of devices
super(CallbackDataBlock, self).__init__(values)
Can someone help me explain the following two lines:
values = {k:0 for k in devices.keys()}
What does k:0 do?
values[0xbeef] = len(values) # the number of devices
Does this mean that new item {0xbeef: length} is appended in the dict?
The k is the field in the dictionary. The set of all fields is stored in the device.keys() which is most probably a list, we loop through the list, take names of fields and initialize them by zero.
Yes, you are right. The next statement is responsible for adding a new field and initializing it to the length of the array.
{k:0 for k in devices.keys()} creates a dictionary with all keys and 0 for all values. And your assessment is correct, it creates a new key with {value of 0xbeef : number of keys in the dictionary}
in python documentation you can see List Comprehensions
this pattern is important :
expression for item in list if conditional else
or for simple usage :
expression for item in list
in list data type we can use :
list = [0,1,2,3,4,5]
a = [x for x in list]
print (a)
printed :
[1,2,3,4,5]
and we have :
a = [x*2 for x in list]
print (a)
printed :
[2,4,6,8,10]
and for dictionary
in dictionary we have this syntax:
{key1:value1, key2:value2, . . .}
and example :
list = [0,1,2,3,4,5]
d = [k:0 for k in list]
print (d)
in example k:0 maens : put 0 for value of each k
printed :
{1: 0, 2: 0, 3: 0, 4: 0, 5: 0}
one more thing :
python dictionary have to Helpful method:dict.keys(),dict.values()
when we use dict.keys, python return a list of dict's keys
d = {"name":"sam", "job":"programer", "salary":"25000"}
print(d.keys())
print(d.values())
printed :
['name','job','salary']
['sam','programer','25000']
for add a new object in a dictionary we use :
d[newkey]= newValue
for example :
d[10] = 'mary'
print(d[10])
printed :
'mary'
now your answer :
in your code
1) k:0 maens : put 0 for value of each k
2) 0xbeef is a hex code == 48879 in decimal
values[48879] = len(values)
its fill by length of list.

Python remove elements matching pattern from array

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.

Python get keys from ordered dict

python noob here. So I'm making a program that will take a JSON file from a url and parse the information and put it into a database. I have the JSON working, thankfully, but now I am stuck, I'll explain it through my code.
playerDict = {
"zenyatta" : 0,
"mei" : 0,
"tracer" : 0,
"soldier76" : 0,
"ana" : 0,
...}
So this is my original dictionary with the which I then fill with the players data for each hero.
topHeroes = sorted(playerDict.items(),key = operator.itemgetter(1),reverse = True)
I then sort this list and it turns the heroes with the most amount of hours played first.
topHeroesDict = topHeroes[0:3]
playerDict['tophero'] = topHeroesDict[0]
I then get the top three heroes. The second line here prints out a list like so:
'secondhero': ('mercy', 6.0)
Whereas I want the output to be:
'secondhero': 'mercy'
Would appreciate any help i have tried the code below with and without list.
list(topHeroes.keys())[0]
So thanks in advance and apologies for the amount of code!
You could take an approach with enumerate, if instead of "firsthero" you are ok with "Top 1" and so on. With enumerate you can iterate over the list and keep track of the current index, which is used to name the key in this dictionary comprehension. j[0] is the name of the hero, which is the first element of the tuple.
topHeroes = sorted(playerDict.items(),key = operator.itemgetter(1),reverse = True)
topHeroesDict = {"Top "+str(i): j[0] for i, j in enumerate(topHeroes[0:3])}
Alternatively, you could use a dictionary which maps the index to first like this:
topHeroes = sorted(playerDict.items(),key = operator.itemgetter(1),reverse = True)
top = {0: "first", 1: "second", 2: "third"}
topHeroesDict = {top[i]+"hero": j[0] for i, j in enumerate(topHeroes[0:3])}
You do not need any imports to achieve this. Without itemgetter, you can do it in one line like this:
top = {0: "first", 1: "second", 2: "third"}
topHeroesDict = {top[i]+"hero": j[0] for i, j in enumerate(sorted([(i, playerDict[i]) for i in playerDict.keys()], key = lambda x: x[1], reverse = True)[0:3])}
You're sorting an iterable of tuples returned by the items method of the dict, so each item in the sorted list is a tuple containing the hero and their score.
You can avoid using sorted and dict.items altogether and get the leading heroes (without their score) by simply using collections.Counter and then getting the most_common 3 heroes.
from collections import Counter
player_dict = Counter(playerDict)
leading_heroes = [hero for hero, _ in player_dict.most_common(3)]

How to tell if a list inside a dict is empty

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

Categories

Resources