Delete first item in each key in a dictionary - python

I'm kind of stumped here and would love some help.
So I have a dictionary like so
{'a':[1, 2, 3], 'b':[4, 5, 6]}
and I need to create a function which will automatically delete the first item in each list/key, so it should become
{'a':[2, 3], 'b':[5, 6]}
I know I should use the pop function, but it kind of gets confusing when there's way more than 2 keys and 3 values

You can use dictionary-comprehension for that:
>>> a = {'a':[1, 2, 3], 'b':[4, 5, 6]}
>>> {k: a[k][1:] for k in a}
{'a': [2, 3], 'b': [5, 6]}

Here's another solution,
dict1={'a':[1, 2, 3], 'b':[4, 5, 6]}
for item in dict1.values():
item.remove(item[0])
The for-loop moves through the values in the dictionary represented by 'dict1.values()'. The values are a set of lists, the '.remove()' function of the list removes the first occurrence of the element given, so if you give it the first element found in the list it would likewise remove it.
Hope this was useful!

You could achieve this with a one-liner using the map built-in function combined with a lambda function. Another advantage of this approach is that there's no copying involved (like in the slicing solution):
doc = {'a':[1, 2, 3], 'b':[4, 5, 6]}
map(lambda v: v.pop(0), doc.values())
This applies list.pop(0) on each value of your dict.

You can loop through the values of the dictionary and pop them one at a time. If you need further functionality or control, you can place it in a function.
dict_ = {'a':[1, 2, 3], 'b':[4, 5, 6]}
for val in dict_.values()
val.pop(0)

You can iterate through the dict & splice the list.
var1 = {'a':[1, 2, 3], 'b':[4, 5, 6]}
for element in var1:
var1[element] = var1[element][1:]

Related

Duplicate integer detection

Update: Wow that was fast! Thank you all for your input, totally overlooked that I was comparing an indice to a value. I’m aware of the shorter methods, the course that I’m on hasn’t shown us the “set” method so I wanted to accomplish the assignment with what was taught. I would upvote all of your comments if I had enough reputation points, thank you all so much!!
First off im an uber-noob to python. I'm learning for the sake of improving my networking administrating skills. The purpose of my code is to remove integers that occur more than once, and to create a new array that doesn't have any duplicate integers. However my code adds in all duplicates, instead of skipping them.
Code:
import array
my_list = [1,1,1,1, 2, 3, 3, 4, 5, 6, 6, 3, 7]
unique_list = []
dupe_list = []
for i in range(len(my_list)):
if i not in unique_list:
unique_list.append(my_list[i])
print("unique array is ", unique_list, 'n', "dupe list: ", dupe_list)
Output:
unique array is [1, 1, 1, 2, 3, 3, 4, 5, 6, 6, 3, 7] n dupe list: []
So basically I have a for-loop that checks whether an integer that is in my_list is also in unique_list, if not then I want the code to add the integer in. However my code is adding every integer into the unique-list regardless of whether it is in there or not. Does the not in function not work the way I think it does?
you can remove integers that occur more then once using set
>>> my_list = [1,1,1,1, 2, 3, 3, 4, 5, 6, 6, 3, 7]
>>> list(set(my_list))
[1, 2, 3, 4, 5, 6, 7]
>>>
As others have pointed out, there are easier ways to accomplish what you're trying to do, but your bug is because you're confusing indices and values.
for i in range(len(my_list)):
if i not in unique_list:
unique_list.append(my_list[i])
In the above code, i is the index of each item in my_list, but you're comparing it against the values in unique_list. One of these things is not like the other!
If you wanted to iterate through by index, you need to use the subscript operator [] to get the value out of my_list:
for i in range(len(my_list)):
if my_list[i] not in unique_list:
unique_list.append(my_list[i])
It would however be simpler to just iterate through by value:
for v in my_list:
if v not in unique_list:
unique_list.append(v)
And of course it's simpler yet to just do:
unique_list = list(set(my_list))
You can use the function dict.fromkeys() to remove duplicates
>>> my_list = [1,1,1,1, 2, 3, 3, 4, 5, 6, 6, 3, 7]
>>> list(dict.fromkeys(my_list))
[1, 2, 3, 4, 5, 6, 7]

Unique list of lists

I have a nested list as an example:
lst_a = [[1,2,3,5], [1,2,3,7], [1,2,3,9], [1,2,6,8]]
I'm trying to check if the first 3 indices of a nested list element are the same as other.
I.e.
if [1,2,3] exists in other lists, remove all the other nested list elements that contain that. So that the nested list is unique.
I'm not sure the most pythonic way of doing this would be.
for i in range(0, len(lst_a)):
if lst[i][:3] == lst[i-1][:3]:
lst[i].pop()
Desired output:
lst_a = [[1,2,3,9], [1,2,6,8]]
If, as you said in comments, sublists that have the same first three elements are always next to each other (but the list is not necessarily sorted) you can use itertools.groupby to group those elements and then get the next from each of the groups.
>>> from itertools import groupby
>>> lst_a = [[1,2,3,5], [1,2,3,7], [1,2,3,9], [1,2,6,8]]
>>> [next(g) for k, g in groupby(lst_a, key=lambda x: x[:3])]
[[1, 2, 3, 5], [1, 2, 6, 8]]
Or use a list comprehension with enumerate and compare the current element with the last one:
>>> [x for i, x in enumerate(lst_a) if i == 0 or lst_a[i-1][:3] != x[:3]]
[[1, 2, 3, 5], [1, 2, 6, 8]]
This does not require any imports, but IMHO when using groupby it is much clearer what the code is supposed to do. Note, however, that unlike your method, both of those will create a new filtered list, instead of updating/deleting from the original list.
I think you are missing a loop For if you want to check all possibilities. I guess it should like :
for i in range(0, len(lst_a)):
for j in range(i, len(lst_a)):
if lst[i][:3] == lst[j][:3]:
lst[i].pop()
Deleting while going throught the list is maybe not the best idea you should delete unwanted elements at the end
Going with your approach, Find the below code:
lst=[lst_a[0]]
for li in lst_a[1:]:
if li[:3]!=lst[0][:3]:
lst.append(li)
print(lst)
Hope this helps!
You can use a dictionary to filter a list:
dct = {tuple(i[:3]): i for i in lst}
# {(1, 2, 3): [1, 2, 3, 9], (1, 2, 6): [1, 2, 6, 8]}
list(dct.values())
# [[1, 2, 3, 9], [1, 2, 6, 8]]

Python Dictionary: Replace values based on key occurrence in other values

My question might involve comprehension if I'm not mistaken.
So I have a dictionary as:
data = {
1: [2, 4],
2: [3],
3: [1, 2, 6],
4: [1, 3, 6],
6: [3, 4]
}
I wish to rearrange the dictionary values (not keys) such that with every occurrence of a "key" in any of the other values, the current key's values should now contain the "key" in who's value it originally occurred.
For example the dictionary should now look like this:
new_data = {
1: [3, 4],
2: [1, 3],
3: [2, 4, 6],
4: [1, 6],
6: [3, 4]
}
I know for sure that I must use another empty dictionary to solve this, and I must use looping. I have a starting point, but it's not efficient:
for pk,pv in zip(data.keys(), data.values()):
#print(pk,pv)
for pvs in pv:
#print(pvs)
if pk == pvs:
new_data.setdefault(pk, [])
new_data[pk].append(pvs)
print(new_data)
Any help is appreciated. Thanks in advance :)
(Using Ubuntu 14.04 32-Bit VM and Python 2.7)
Perhaps this is not the most efficient way to do this, but I would argue it's one of the nicest to read :).
One thing I should say before, if it's possible to change the initial dictionary values to set instead of list, that could result in some performance gains since set membership checks can be faster than listss.
Here goes:
def present_in(k, d):
return {idx for idx in d if k in d[idx]}
new_data = {k: present_in(k, data) for k in data}
Basically the present_in function creates a set of values corresponding to keys where k is present as a member. We simply then use this to create the new_data dictionary using a dictionary comprehension. Note again the values of this dictionary is a set, instead of a list. You can easily wrap them in list() if you do need lists.
EDIT:
If you would like new_data to have keys that may be missing as keys in data but present as one of the values, you can change the code to create a set of all possible keys first:
all_keys = {v for vs in data.values() for v in vs}
def present_in(k, d):
return {idx for idx in d if k in d[idx]}
new_data = {k: present_in(k, data) for k in all_keys}
{k:[i for i,j in data.items() if k in j] for k,_ in data.items()}
#Output:
#{1: [3, 4], 2: [1, 3], 3: [2, 4, 6], 4: [1, 6], 6: [3, 4]}
The below part essentially checks if the key(k from outer dict) is present in any of the values in dict, if present, it'll get the corresponding key into the list
[i for i,j in data.items() if k in j]

Nested list sort python 3

I am a python beginner--headbangin'. This is a very basic question and I can't seem to find any straight forward answer, either using google or StackOverFlow.
QUESTION:
I have a nested list:
l = [
[1,4,3,n]
[2,2,4,n]
[3,1,5,n]
]
I want to sort the entire list by the second value smallest to largest. I will end up sorting the list again by the third value... and nth value of each nested list.
HOW WOULD ONE SORT based on the SECOND, THIRD, Nth value?
A key is mentioned, but "key=lambda" is often used and that just confuses me more.
EDIT: Thank you guys for your help. I was able to use your advice to solve the problem at hand. I would upvote you but apparently, I can't yet show my thanks in that form. I will return someday and give you your reputation bumps.
Can also be done using operator
Inside operator.itemgetter(1) you are indicating which index you want to sort on. So, in in this case we are specifying 1 which is the second item.
import operator
l = [[1,4,3], [2,2,4], [3,1,5]]
print(sorted(l, key=operator.itemgetter(1)))
output:
[[3, 1, 5], [2, 2, 4], [1, 4, 3]]
You can try like this,
>>> l = [[1,4,3], [2,2,4], [3,1,5]]
>>> sorted(l, key=lambda x: x[1])
[[3, 1, 5], [2, 2, 4], [1, 4, 3]]
or:
>>> l.sort(key=lambda x: x[1])
>>> l
[[3, 1, 5], [2, 2, 4], [1, 4, 3]]

Python - dividing a list-of-lists to groups

Consider the following simplified case:
lol = [['John','Polak',5,3,7,9],
['John','Polak',7,9,2,3],
['Mark','Eden' ,0,3,3,1],
['Mark','Eden' ,5,1,2,9]]
What would be a pythonic and memory+speed efficient way to transform this list-of-lists to a list-of-lists-of-lists based on the first two parameters:
lolol = [[['John','Polak',5,3,7,9],
['John','Polak',7,9,2,3]],
[['Mark','Eden' ,0,3,3,1],
['Mark','Eden' ,5,1,2,9]]]
Actually - any other data structure would also be ok, as long as I have the correct hierarchy. For example the following dictionary structure comes to mind, but creating it doesn't seem efficient speed-efficient enough, and the memory would probably be higher than the lolol solution.
dolol = {('John','Polak'):[[5,3,7,9],[7,9,2,3]],
('Mark','Eden') :[[0,3,3,1],[5,1,2,9]]}
List:
from itertools import groupby
lolol = [list(grp) for (match, grp) in groupby(lol, lambda lst: lst[:2])]
# [[['John', 'Polak', 5, 3, 7, 9], ['John', 'Polak', 7, 9, 2, 3]],
# [['Mark', 'Eden', 0, 3, 3, 1], ['Mark', 'Eden', 5, 1, 2, 9]]]
Dictionary:
dolol = dict((tuple(match), [x[2:] for x in grp]) for (match, grp) in
groupby(lol, lambda lst: lst[:2]))
# {('John', 'Polak'): [[5, 3, 7, 9], [7, 9, 2, 3]],
# ('Mark', 'Eden'): [[0, 3, 3, 1], [5, 1, 2, 9]]}
Since itertools.groupby works on consecutive matches, it assumes sorted input (lol).
If a dictionary is acceptable, this code will create one:
import collections
d = collections.defaultdict(list)
for name, surname, *stuff in lol:
d[name, surname].append(nums)
Note that this requires Python 3 (extended iterable unpacking). For Python 2, use
for x in lol:
name = x[0]
surname = x[1]
stuff = x[2:]
You may fold the variables to save lines.
To complement delnan's answer with a Python 2 equivalent:
from collections import defaultdict
dolol=defaultdict(list)
for data in lol:
dolol[data[0],data[1]].append(data[2:])

Categories

Resources