Having a list like this
lst = ['a','b','a','c','a','b','b']
I'd like to get lists of indexes for each unique element to get this:
indexes = {
'a': [0,2,4],
'b': [1,5,6],
'c': [3]
}
This is my current code, but I'm only getting the first index of each element.
indexes= dict()
for el in lst:
indexes[el] = [lst.index(el)]
>>> indexes
{'a': [0], 'b': [1], 'c': [3]}
Thanks for any help.
The problem with you code is you're overriding the same key again and again but with a different list, so your final dictionary contains only a single list.
you can avoid this behavior by using defaultdict.
from collections import defaultdict
lst = ["a", "b", "a", "c", "a", "b", "b"]
lst = [c for c in lst if c.strip()] # this will remove empty strings
indexes = defaultdict(list)
for index, char in enumerate(lst):
indexes[char].append(index)
indexes = dict(indexes)
print(indexes)
Output:
{'a': [0, 2, 4], 'b': [1, 5, 6], 'c': [3]}
Related
I have the following list of dicts:
lst = [{'a':1, 'b':2, 'c':3}, {'a':1, 'b':2, 'd':3}, {'a':1, 'c':2, 'k':3}, {'d':1, 'k':2, 'l':3}]
I want to filter the list of dicts (in my case it's a list of thousands or even more dicts, with different keys with some overlap) to be a list containing all the dicts that have keys: ["a", "b"]. I want to filter each dict only to these a and b keys, and if they don't exist, don't include the dictionary in the final list. I am using:
[{"a": d.get("a"), "b": d.get("b")} for d in lst]
Please advise for an elegant way to solve it.
The dictionary keys-view is set-like, so it supports subset comparisons by using <= operator:
>>> keys = set("ab")
>>> [{k: d[k] for k in keys} for d in lst if keys <= d.keys()]
[{'a': 1, 'b': 2}, {'a': 1, 'b': 2}]
I have figured it out and here is my alternative:
lst = [{'a':1, 'b':2, 'c':3}, {'a':1, 'b':2, 'd':3}, {'a':1, 'c':2, 'k':3}, {'d':1, 'k':2, 'l':3}]
keys = set("ab")
[i for i in [{k: d.get(k) for k in keys if k in d} for d in lst] if i]
Gives the desired answer:
[{'b': 2, 'a': 1}, {'b': 2, 'a': 1}, {'a': 1}]
I have a list of the dictionary as follows:
[{"A":5,"B":10},
{"A":6,"B":13},
{"A":10,"B":5}]
I want to this list in decending order on the value of B. The output should look like this:
[{"A":6,"B":13},
{"A":5,"B":10},
{"A":10,"B":5}]
How to do that?
You can sort lists by the results of applying a function to each element: https://docs.python.org/3.9/library/functions.html#sorted
>>> data = [{"A":5,"B":10},
... {"A":6,"B":13},
... {"A":10,"B":5}]
>>> sorted(data, key=lambda dct: dct["B"], reverse=True)
[{'A': 6, 'B': 13}, {'A': 5, 'B': 10}, {'A': 10, 'B': 5}]
I have the following for instance:
x = [{'A':1},{'A':1},{'A':2},{'B':1},{'B':1},{'B':2},{'B':3},{'C':1},{'D':1}]
and I would like to get a dictionary like this:
x = [{'A': [1,2], 'B': [1,2,3], 'C':[1], 'D': [1]}]
Do you have any idea how I could get this please?
You could use a collections.defaultdict of sets to collect unique values, then convert the final result to a dictionary with values as lists using a dict comprehension:
from collections import defaultdict
lst = [{'A':1},{'A':1},{'A':2},{'B':1},{'B':1},{'B':2},{'B':3},{'C':1},{'D':1}]
result = defaultdict(set)
for dic in lst:
for key, value in dic.items():
result[key].add(value)
print({key: list(value) for key, value in result.items()})
Output:
{'A': [1, 2], 'B': [1, 2, 3], 'C': [1], 'D': [1]}
Although its probably better to add your data directly to the defaultdict to begin with, instead of creating a list of singleton dictionaries(don't recommend this data structure) then converting the result.
Using dict.setdefault
Ex:
x = [{'A':1},{'A':1},{'A':2},{'B':1},{'B':1},{'B':2},{'B':3},{'C':1},{'D':1}]
res = {}
for i in x:
for k, v in i.items():
res.setdefault(k, set()).add(v)
#or res = [{k: list(v) for k, v in res.items()}]
print(res)
Output:
{'A': {1, 2}, 'B': {1, 2, 3}, 'C': {1}, 'D': {1}}
I have two lists:
a = ["A", "B", "B", "C", "D", "A"]
b = [1, 2, 3, 4, 5, 6]
I want to have a dictionary like the one below:
d = {"A":[1, 6], "B":[2, 3], "C":[4], "D":[5]}
Right now I am doing something like this:
d = {i:[] for i in set(a)}
for c in zip(a, b):
d[c[0]].append(c[1])
Is there a better way to do this?
You can use the dict.setdefault method to initialize each key as a list and then append the current value to it while you iterate:
d = {}
for k, v in zip(a, b):
d.setdefault(k, []).append(v)
With the sample input, d would become:
{'A': [1, 6], 'B': [2, 3], 'C': [4], 'D': [5]}
Running your code, didnt produce the output what you wanted. The below is a bit more verbose but makes it easy to see what the code is doing.
a = ["A", "B", "B", "C", "D", "A"]
b = [1, 2, 3, 4, 5, 6]
c = {}
for a, b in zip(a, b):
if a in c:
if isinstance(a, list):
c[a].append(b)
else:
c[a] = [c[a], b]
else:
c[a] = b
print(c)
OUTPUT
{'A': [1, 6], 'B': [2, 3], 'C': 4, 'D': 5}
An alternative less verbose mode would be to use a default dict with list as the type, you can then append all the items to it. this will mean even single items will be in a list. to me its much cleaner as you will know the data type of each item in the list. However if you really do want to have single items not in a list you can clean it up with a dict comprehension
from collections import defaultdict
a = ["A", "B", "B", "C", "D", "A"]
b = [1, 2, 3, 4, 5, 6]
c = defaultdict(list)
for a, b in zip(a, b):
c[a].append(b)
d = {k: v if len(v) > 1 else v[0] for k, v in c.items()}
print(c)
print(d)
OUTPUT
defaultdict(<class 'list'>, {'A': [1, 6], 'B': [2, 3], 'C': [4], 'D': [5]})
{'A': [1, 6], 'B': [2, 3], 'C': 4, 'D': 5}
According to the official docs the dictionary copy is shallow, i.e. it returns a new dictionary that contains the same key-value pairs:
dict1 = {1: "a", 2: "b", 3: "c"}
dict1_alias = dict1
dict1_shallow_copy = dict1.copy()
My understanding is that if we del an element of dict1 both dict1_alias & dict1_shallow_copy should be affected; however, a deepcopy would not.
del dict1[2]
print(dict1)
>>> {1: 'a', 3: 'c'}
print(dict1_alias)
>>> {1: 'a', 3: 'c'}
But dict1_shallow_copy 2nd element is still there!
print(dict1_shallow_copy)
>>> {1: 'a', 2: 'b', 3: 'c'}
What am I missing?
A shallow copy means that the elements themselves are the same, just not the dictionary itself.
>>> a = {'a':[1, 2, 3], #create a list instance at a['a']
'b':4,
'c':'efd'}
>>> b = a.copy() #shallow copy a
>>> b['a'].append(2) #change b['a']
>>> b['a']
[1, 2, 3, 2]
>>> a['a'] #a['a'] changes too, it refers to the same list
[1, 2, 3, 2]
>>> del b['b'] #here we do not change b['b'], we change b
>>> b
{'a': [1, 2, 3, 2], 'c': 'efd'}
>>> a #so a remains unchanged
{'a': [1, 2, 3, 2], 'b': 4, 'c': 'efd'}1