Double Nesting defaultdict - python

Poked around but couldn't figure it out, probably a very simple solution but please help me understand.
Source (sample.txt):
1,1,2,3
2,3,2,4,4
This:
import csv
from collections import defaultdict
input = "sample.txt"
with open(input) as f:
r = csv.reader(f)
d = defaultdict(list)
rlabel = 1
for row in r:
d[rlabel].append(row)
rlabel += 1
print(d)
Gets This:
defaultdict(<class 'list'>, {1: [['1', '1', '2', '3']], 2: [['2', '3', '2', '4', '4']]})
Why are there double brackets around my lists?

Why are there double brackets around my lists?
Your code works exactly as expected. The key point is the usage of extend and append.
append adds the parameter you passed as a single element. Due to a list is an object and your defaultdict class is list, so the list is appended as a list of lists.
extend method iterate in the input and extend the original list by adding all elements from an iterable.
So, in this case, if you want to add a single list to your defaultdict you should use list.extend method. And your output will be:
defaultdict(<class 'list'>, {1: ['1', '1', '2', '3'], 2: ['2', '3', '2', '4', '4']})

With a defaultdict, when a key is created a default value is associated to it
>>> d = defaultdict(list)
>>> 'a' in d[1]
False
>>> d
defaultdict(<class 'list'>, {1: []})
Given that your row is a list, you are appending a list to the list associated with the key.
To add the elements you can do
d[rlabel]+= row

Related

How to compare each element of multiple lists and return name of lists which are different

I am having multiple lists and I need to compare each list with one another and return the name of lists which are different. We need to consider value of elements in list irrespective of their position while comparing lists.
For example:-
Lis1=['1','2','3']
Lis2=['1','2']
Lis3=['0','1','3']
Lis4=[]
Lis5=['1','2']
Output:-
['Lis1','Lis2','Lis3','Lis4']
Thanks in advance.
Try this:
input_lists = {"Lis1": ['1', '2', '3'], "Lis2": ['1', '2'],
"Lis3": ['0', '1', '3'], "Lis4": [], "Lis5": ['1', '2']}
output_lists = {}
for k, v in input_lists.items():
if sorted(v) not in output_lists.values():
output_lists[k] = sorted(v)
unique_keys = list(output_lists.keys())
print(unique_keys) # ['Lis1', 'Lis2', 'Lis3', 'Lis4']
import itertools
Lis1=['1','2','3']
Lis2=['1','2']
Lis3=['0','1','3']
Lis4=[]
Lis5=['1','2']
k=[Lis1,Lis2,Lis3,Lis4,Lis5]
k.sort()
list(k for k,_ in itertools.groupby(k))
output
[[], ['0', '1', '3'], ['1', '2'], ['1', '2', '3']]
a simple way to implement
Lis1=['1','2','3']
Lis2=['1','2']
Lis3=['0','1','3']
Lis4=[]
Lis5=['1','2']
lis=[Lis1,Lis2,Lis3,Lis4,Lis5]
final=[]
for ele in lis:
if(ele not in final):
final.append(ele)
print(final)
with your given data you can use:
Lis1=['1','2','3']
Lis2=['1','2']
Lis3=['0','1','3']
Lis4=[]
Lis5=['1','2']
name_lis = {'Lis1': Lis1, 'Lis2': Lis2, 'Lis3': Lis3, 'Lis4': Lis4, 'Lis5': Lis5}
tmp = set()
response = []
for k, v in name_lis.items():
s = ''.join(sorted(v))
if s not in tmp:
tmp.add(s)
response.append(k)
print(response)
output:
['Lis1', 'Lis2', 'Lis3', 'Lis4']
name_lis dictionary contains the name of your list and the actual list, you are iterating over each list, and for each list, you are sorting the elements and then converting in a string, if the string was encountered before you know that the list is a duplicate if not you are adding the list to the response

create a list of dictionaries from two lists of tuples

I have a set of tuples:
users = set(("test#a.com","password"),("test#b.com","password"))
but could be simplified to a set...and a list of tuples:
licences = [("test#a.com","22"),("test#a.com","23"),("test#b.com","12")]
For every entry of the list the username could be repeated with different "licence" values.
I need to build a list of dictionaries like this:
[{"user":"test#a.com", "licences":["22","23"]},{"user":"test#b.com", "licences":["12"]}]
What I've done so far is this:
licenzadiz = []
for num,user in enumerate(users):
licenzadiz.append({'user': user[0], 'licences': []})
for num2,licence in enumerate(licences):
if user[0] == licence[0]:
licenzadiz[num]['licences'].append(licence[1])
that is working well. BUT I wonder if there are more elegant solutions to my problem.
You can get fancy with nested default dicts:
from collections import defaultdict
items = [('A','1'),('A','3'),('A','2'),
('B','0'),('B','4'),('B','-1'),
('C','7'),('C','6'),('C','12')]
d = defaultdict(lambda: defaultdict(list))
for use,lic in items:
d[use]['username'] = use #<-- Overwrites each time an already known key is found, but thats ok
d[use]['licence'].append(lic)
#Just for printout
for use in d:
print d[use]
print d[use]['username']
print d[use]['licence']
Output:
defaultdict(<type 'list'>, {'username': 'A', 'licence': ['1', '3', '2']})
A
['1', '3', '2']
defaultdict(<type 'list'>, {'username': 'C', 'licence': ['7', '6', '12']})
C
['7', '6', '12']
defaultdict(<type 'list'>, {'username': 'B', 'licence': ['0', '4', '-1']})
B
['0', '4', '-1']
data = {}
for num2,(email, license) in enumerate(licenze):
data.setdefault(email,[]).append(license)
print data #dictionary of email:[licenses,..]
#or
print data.items() # if you want a list
I guess ... i think

splitting lists and storing in dictionary in python

Suppose I have a list such as
L = ['B0','B1','C1','C2','D1','D3']
Then How do I split the list into values and keys and store it in a dictionary in the following form:-
{ 'B':['0','1'],
'C':['1','2'],
'D':['1','3']}
L = ['B0','B1','C1','C2','D1','D3']
d = {}
for i in L:
d.setdefault(i[0], []).append(i[1])
>>> d
{'B': ['0', '1'], 'C': ['1', '2'], 'D': ['1', '3']}
You can iterate over the list and break each string element to create a dictionary. Try this:
from collections import defaultdict
l = ['B0','B1','C1','C2','D1','D3']
d = defaultdict(list)
for key, value in l:
d[key].append(value)
print d

How to remove specific strings from a list

From the following list how can I remove elements ending with Text.
My expected result is a=['1,2,3,4']
My List is a=['1,2,3,4,5Text,6Text']
Should i use endswith to go about this problem?
Split on commas, then filter on strings that are only digits:
a = [','.join(v for v in a[0].split(',') if v.isdigit())]
Demo:
>>> a=['1,2,3,4,5Text,6Text']
>>> [','.join(v for v in a[0].split(',') if v.isdigit())]
['1,2,3,4']
It looks as if you really wanted to work with lists of more than one element though, at which point you could just filter:
a = ['1', '2', '3', '4', '5Text', '6Text']
a = filter(str.isdigit, a)
or, using a list comprehension (more suitable for Python 3 too):
a = ['1', '2', '3', '4', '5Text', '6Text']
a = [v for v in a if v.isdigit()]
Use str.endswith to filter out such items:
>>> a = ['1,2,3,4,5Text,6Text']
>>> [','.join(x for x in a[0].split(',') if not x.endswith('Text'))]
['1,2,3,4']
Here str.split splits the string at ',' and returns a list:
>>> a[0].split(',')
['1', '2', '3', '4', '5Text', '6Text']
Now filter out items from this list and then join them back using str.join.
try this. This works with every text you have in the end.
a=['1,2,3,4,5Text,6Text']
a = a[0].split(',')
li = []
for v in a:
try : li.append(int(v))
except : pass
print li

Python 2,7 Dictionary Advice

I do not use dictionary objects often in Python. I've been working on a script that is going to require me to use a dictionary to store dynamically created list'esque information. How can I append a value to a list of values belonging to one key in a dictionary in Python? Is this possible? I would hope to be able to create this type of information from which I could pull later...
dict = {'PhysicalDrive0': '0', '1', '2', 'PhysicalDrive1': '0', '1'};
dict[PhysicalDrive0].append(3)
dict[PhysicalDrive1].append(2)
print dict[PhysicalDrive0]
<0, 1, 2, 3>
print dict[PhysicalDrive1]
<0, 1, 2>
Thanks!
Use a list as value, list will allow you to append new items:
>>> dic = {'PhysicalDrive0': ['0', '1', '2'], 'PhysicalDrive1': ['0', '1']}
>>> dic['PhysicalDrive0'].append('3')
>>> dic['PhysicalDrive1'].append('2')
>>> dic
{'PhysicalDrive1': ['0', '1', '2'], 'PhysicalDrive0': ['0', '1', '2', '3']}
To append to a value to a missing key you can use dict.setdefault, if the key is already present then it'll append value to the already present list otherwise creates a key with an empty list and then appends the value to it.
Demo:
#creates a new key PhysicalDrive3' and appends a value to it.
>>> dic.setdefault('PhysicalDrive3', []).append('3')
>>> dic
{'PhysicalDrive1': ['0', '1', '2'], 'PhysicalDrive0': ['0', '1', '2', '3'], 'PhysicalDrive3': ['3']}
>>> dic.setdefault('PhysicalDrive1', []).append('5')
>>> dic
{'PhysicalDrive1': ['0', '1', 2, '5'], 'PhysicalDrive0': ['0', '1', '2', 3], 'PhysicalDrive3': [3]}
You should look at collections.defaultdict if you can't simply store the value as a list literal...:
from collections import defaultdict
dd = defaultdict(list)
dd['Drive1'].append(3)
dd['Drive2'].append(6)
dd['Drive1'].append(2)
# defaultdict(<type 'list'>, {'Drive2': [6], 'Drive1': [3, 2]})
dict = {'PhysicalDrive0': ['0', '1', '2'], 'PhysicalDrive1': ['0', '1']}
This should work as stated. The value stored in the dictionary is a list - which you can handle as normal.
This, of course, means that you can access the items of the list as:
dict['PhysicalDrive0'][0]
etc.
Your syntax is invalid, the value half of your key-value needs to be a single item, it can be a list, however so you could say 'PhysicalDrive0':['0','1','2']
You would then append to that key-value pair in the dictionary by saying dict['PhysicalDrive0'].append('3')

Categories

Resources