How to remove a character from the values of a dictionary? - python-3.x

dict_data = {'c': ['d\n', 'e\n'], 'm':['r\n','z\n','o']}
a dictionary dict_data remove '\n' in the values
(order is not important.):
should return: {'c': ['d', 'e'], 'm':['r','z','o']}
This is what I tried:
def dicts(dict_data):
for k, v in dict_data.items():
for i in v:
f = i.strip('\n')
return f
How can i get this without doing anything to complicated?

You were on the right approach but you've probably assumed that altering i with i.strip('\n') in for i in v might make the change appear in dict_data. This isn't the case. What you're doing is altering i and then discarding the result.
A correct approach would be to build a list of the stripped elements and re-assign to the corresponding dictionary key:
def strip_dicts(dict_data):
for k, v in dict_data.items():
f = []
for i in v:
f.append(i.strip('\n'))
dict_data[k] = f
of course, remember, this alters the argument dictionary in-place.
You can create a different function that returns a new dictionary by using a comprehension:
def strip_dicts(d):
return {k: [i.strip() for i in v] for k,v in d.items()}

Related

Merge dictionaries to overwrite duplicate keys without overwriting duplicate and non-duplicate values

Input:
dict1 = {a: [xxx, zzz]}
dict2 = {a: [yyy, zzz]}
Desired output:
dict3 = {a: [xxx, zzz, yyy, zzz]}
I have tried:
dict3 = dict1 | dict2
and
dict3 = dict1.copy()
d3 |= d2
However, the merge | and update |= operators overwrites with the last seen dict as precedence, resulting in:
dict3 = {a: [yyy, zzz]}
This is the desired result, as stated in the PEP 584,
Dict union will return a new dict consisting of the left operand
merged with the right operand, each of which must be a dict (or an
instance of a dict subclass). If a key appears in both operands, the
last-seen value (i.e. that from the right-hand operand) wins
You may need to merge two dict by hands:
In [8]: dict1 = {'a': ['xxx', 'zzz']}
...: dict2 = {'a': ['yyy', 'zzz']}
...: for k, v in dict2.items():
...: if k in dict1:
...: dict1[k] += v
...:
In [9]: print(dict1)
{'a': ['xxx', 'zzz', 'yyy', 'zzz']}
The answer from xiez does not perform what the OP requested, for two reasons:
It updates the dict1 instead of creating a new, independent dict3
It misses out all items that exist solely in dict2, because it reacts only on those present in dict1 (line 4) - although this is not apparent from the one given example
A possible solution:
dict3 = {
k: dict1.get(k, []) + dict2.get(k, [])
for k in set(dict1) | set(dict2)
}
For each key in the united set of keys of both source dicts, we use the dicts' get function to extract the value of the key, if existing, or get the default empty list. Then we create the new dict3 by blindly adding the found or default lists for each key.

sort values of lists inside dictionary based on length of characters

d = {'A': ['A11117',
'33465'
'17160144',
'A11-33465',
'3040',
'A11-33465 W1',
'nor'], 'B': ['maD', 'vern', 'first', 'A2lRights']}
I have a dictionary d and I would like to sort the values based on length of characters. For instance, for key A the value A11-33465 W1 would be first because it contains 12 characters followed by 'A11-33465' because it contains 9 characters etc. I would like this output:
d = {'A': ['A11-33465 W1',
' A11-33465',
'17160144',
'A11117',
'33465',
'3040',
'nor'],
'B': ['A2lRights',
'first',
'vern',
'maD']}
(I understand that dictionaries are not able to be sorted but I have examples below that didn't work for me but the answer contains a dictionary that was sorted)
I have tried the following
python sorting dictionary by length of values
print(' '.join(sorted(d, key=lambda k: len(d[k]), reverse=True)))
Sort a dictionary by length of the value
sorted_items = sorted(d.items(), key = lambda item : len(item[1]))
newd = dict(sorted_items[-2:])
How do I sort a dictionary by value?
import operator
sorted_x = sorted(d.items(), key=operator.itemgetter(1))
But they both do not give me what I am looking for.
How do I get my desired output?
You are not sorting the dict, you are sorting the lists inside it. The simplest will be a loop that sorts the lists in-place:
for k, lst in d.items():
lst.sort(key=len, reverse=True)
This will turn d into:
{'A': ['3346517160144', 'A11-33465 W1', 'A11-33465', 'A11117', '3040', 'nor'],
'B': ['A2lRights', 'first', 'vern', 'maD']}
If you want to keep the original data intact, use a comprehension like:
sorted_d = {k: sorted(lst, key=len, reverse=True) for k, lst in d.items()}

Check if element is occurring very first time in python list

I have a list with values occurring multiple times. I want to loop over the list and check if value is occurring very first time.
For eg: Let's say I have a one list like ,
L = ['a','a','a','b','b','b','b','b','e','e','e'.......]
Now, at every first occurrence of element, I want to perform some set of tasks.
How to get the first occurrence of element?
Thanks in Advance!!
Use a set to check if you had processed that item already:
visited = set()
L = ['a','a','a','b','b','b','b','b','e','e','e'.......]
for e in L:
if e not in visited:
visited.add(e)
# process first time tasks
else:
# process not first time tasks
You can use unique_everseen from itertools recipes.
This function returns a generator which yield only the first occurence of an element.
Code
from itertools import filterfalse
def unique_everseen(iterable, key=None):
"List unique elements, preserving order. Remember all elements ever seen."
# unique_everseen('AAAABBBCCDAABBB') --> A B C D
# unique_everseen('ABBCcAD', str.lower) --> A B C D
seen = set()
seen_add = seen.add
if key is None:
for element in filterfalse(seen.__contains__, iterable):
seen_add(element)
yield element
else:
for element in iterable:
k = key(element)
if k not in seen:
seen_add(k)
yield element
Example
lst = ['a', 'a', 'b', 'c', 'b']
for x in unique_everseen(lst):
print(x) # Do something with the element
Output
a
b
c
The function unique_everseen also allows to pass a key for comparison of elements. This is useful in many cases, by example if you also need to know the position of each first occurence.
Example
lst = ['a', 'a', 'b', 'c', 'b']
for i, x in unique_everseen(enumerate(lst), key=lambda x: x[1]):
print(i, x)
Output
0 a
2 b
3 c
Why not using that?
L = ['a','a','a','b','b','b','b','b','e','e','e'.......]
for idxL, L_idx in enumerate(L):
if (L.index(L_idx) == idxL):
print("This is first occurence")
For very long lists, it is less efficient than building a set prior to the loop, but seems more direct to write.

Merge Keys by common value from the same dictionary

Let's say that I have a dictionary that contains the following:
myDict = {'A':[1,2], 'B': [4,5], 'C': [1,2]}
I want to create a new dictionary, merged that merges keys by having similar values, so my merged would be:
merged ={['A', 'C']:[1:2], 'B':[4,5]}
I have tried using the method suggested in this thread, but cannot replicate what I need.
Any suggestions?
What you have asked for is not possible. Your keys in the hypothetical dictionary use mutable lists. As mutable data can not be hashed, you cant use them as dictionary keys.
Edit, I had a go to doing what you asked for except the keys in this are all tuples. This code is a mess but you may be able to clean it up.
myDict = {'A':[1,2],
'B': [4,5],
'C': [1,2],
'D': [1, 2],
}
myDict2 = {k: tuple(v) for k, v in myDict.items()}
print(myDict2) #turn all vlaues into hasable tuples
#make set of unique keys
unique = {tuple(v) for v in myDict.values()}
print(unique) #{(1, 2), (4, 5)}
"""
iterate over each value and make a temp shared_keys list tracking for which
keys the values are found. Add the new key, vlaue pairs into a new
dictionary"""
new_dict = {}
for value in unique:
shared_keys = []
for key in myDict:
if tuple(myDict[key]) == value:
shared_keys.append(key)
new_dict[tuple(shared_keys)] = value
print(new_dict) #{('A', 'C'): (1, 2), ('B',): (4, 5)}
#change the values back into mutable lists from tuples
final_dict = {k: list(v) for k, v in new_dict.items()}
print(final_dict)

Translating for loop into list comprehension

I can get this loop to work properly:
for x in range(0,len(l)):
for k in d:
if l[x] in d[k]:
l[x] = k
This looks through a list and checks if the value is in any of the dictionary items and then calculates it equal to the dictionary key it is found within (the dictionary contains lists.)
However, I want to convert to a list comprehension or other single line statement for use in a pandas dataframe - to populate a field based on whether or not another field's value is in the labeled dictionary keys and assign it the dictionary key value.
Here is my best attempt, but it does not work:
l = [ k for x in range(0,len(l)) if l[x] in d[k] for k in d ]
Thanks
Assuming I understand what you're after (example data that can be copied and pasted is always appreciated), I'd do something like this:
>>> l = ["a", "b", "c", "d"]
>>> d = {1: ["a"], 3: ["d", "c"]}
>>> l2 = [next((k for k,v in d.items() if lx in v), lx) for lx in l]
>>> l2
[1, 'b', 3, 3]
Don't forget to think about what behaviour you want if an entry in l is found in multiple lists in d, of course, although that may not be an issue with your data.
You can't do it with a list comprehension, because you have an assignment:
l[x] = k
which is an statement, and a list comprehension can't have them.

Resources