Create list of tuples from empty dict - python

I would like to create a dict where the value is a list of tuples
The code below produces a dict with lists of numbers, not list of tuples
mydict = {}
for line in file:
# read a
# read b
# read c
mydict[a] = (b, c) if a not in mydict else mydict[a].append((b, c))

Use defaultdict:
from collections import defaultdict
mydict = defaultdict(list)
for line in file:
a,b,c = line.split() # or something else
mydict[a].append((b,c))

You can also use setdefault when using normal dict's
mydict = {}
mydict.setdefault(a, list()).append((b,c))

Related

How to print values from a file?

I have a text file and its content is something like this:
A:3
B:5
C:7
A:8
C:6
I need to print:
A numbers: 3, 8
B numbers: 5
C numbers: 7, 6
I'm a beginner so if you could give some help I would appreciate it. I have made a dictionary but that's pretty much all I know.
You could use an approach that keeps the values in a dictionary:
d = {} # create an empty dictionary
for line in open(filename): # opens the file
k, v = line.split(':') # unpack each line in the char before : and after
if k in d: # add the values to the dictionary
d[k].append(v)
else:
d[k] = [v]
This gives you a dictionary containing your file in a format that you can utilize to get the desired output:
for key, values in sorted(d.items()):
print(key, 'numbers:' ', '.join(values))
The sorted is required because dictionaries are unordered.
Note that using collections.defaultdict instead of a normal dict could simplify the approach somewhat. The:
d = {}
...
if k in d: # add the values to the dictionary
d[k].append(v)
else:
d[k] = [v]
could then be replaced by:
from collections import defaultdict
d = defaultdict(list)
...
d[k].append(v)
Short version (Which should sort in alphabetic order)
d = {}
lines = [line.rstrip('\n') for line in open('filename.txt')]
[d.setdefault(line[0], []).append(line[2]) for line in lines]
[print(key, 'numbers:', ', '.join(values)) for key,values in sorted(d.items())]
Or if you want to maintain the order as they appear in file (file order)
from collections import OrderedDict
d = OrderedDict() # Empty dict
lines = [line.rstrip('\n') for line in open('filename.txt')] # Get the lines
[d.setdefault(line[0], []).append(line[2]) for line in lines] # Add lines to dictionary
[print(key, 'numbers:', ', '.join(values)) for key,values in d.items()] # Print lines
Tested with Python 3.5.
You can treat your file as csv (comma separated value) so you can use the csv module to parse the file in one line. Then use defaultdict with input in the costructor the class list to say that to create it when the key not exists. Then use OrderedDict class because standard dictionary don't keeps the order of your keys.
import csv
from collection import defaultdict, OrderedDict
values = list(csv.reader(open('your_file_name'), delimiter=":")) #[['A', '3'], ['B', '5'], ['C', '7'], ['A', '8'], ['C', '6']]
dct_values = defaultdict(list)
for k, v in values:
dct_values[k].append(v)
dct_values = OrderedDict(sorted(dct_values.items()))
Then you can simply print iterating the dictionary.
A very easy way to group by key is by external library, if you are interested try PyFunctional

operations with elements in list of list in python

This is my list:
volume = [['1.986', '3000'], ['1.987', '2000'], ['1.986', '700'],['1.987', '4000']]
How can I get the sum of volume[1] when volume[0] is the same price?
results = [['1.986', '3700'], ['1.987', '6000']]
Dictionaries would be a good data structure to use here. The default dict holds unique strings as the keys and assumes empty values are 0 because I set it to be based off of int.
from collections import defaultdict
d = defaultdict(int)
for v in volume:
d[v[0]] += int(v[1])
print d
If you need a list afterwards you can use a list comprehension:
list_version = [[key, value] for key,value in d]

Merging two dictionaries with order saving

I have two dictionaries:
a = {u'Anthracite': [u'3/optimized/8593793_fpx.tif'],
u'Black': [u'6/optimized/8593796_fpx.tif'],
u'Cobalt': [u'9/optimized/8593799_fpx.tif'],
u'Fire': [u'2/optimized/8593802_fpx.tif'],
u'Fuschia': [u'5/optimized/8593805_fpx.tif'],
u'Iris': [u'8/optimized/8593808_fpx.tif'],
u'Midnight': [u'1/optimized/8593811_fpx.tif']}
b = {u'Anthracite': [u'5/optimized/8593795_fpx.tif'],
u'Black': [u'8/optimized/8593798_fpx.tif'],
u'Cobalt': [u'1/optimized/8593801_fpx.tif'],
u'Fire': [u'4/optimized/8593804_fpx.tif'],
u'Fuschia': [u'7/optimized/8593807_fpx.tif'],
u'Iris': [u'0/optimized/8593810_fpx.tif'],
u'Midnight': [u'3/optimized/8593813_fpx.tif']}
I need to produce such dict:
c = {u'Anthracite': [u'3/optimized/8593793_fpx.tif', u'5/optimized/8593795_fpx.tif'],
u'Black': [u'6/optimized/8593796_fpx.tif', u'8/optimized/8593798_fpx.tif'],
....
}
So I need to collect all items from lists with same keys, but I need to save first order.
Dictionaries always have same keys
I have try to do this with zip but I`m getting total mess
Why not just iterating over the dictionaries and copy them to a new dictionary? A defaultdict is used in the following code for simplicity :
from collections import defaultdict
c = defaultdict(list)
a = {"foo": ["bar"]}
b = {"foo": ["baz"], "bah": ["foo"]}
for k, v in a.items() + b.items():
c[k].extend(v)
If the keys are the same, you can copy the first dictionary and update its content :
d = a.copy()
for k, v in b.iteritems():
d[k].extend(v)
Note that the latter creates a shallow copy and therefore the dictionary a is also modified during the process.
If you want alphabetical order, use an OrderedDict and sort the keys:
from collections import OrderedDict
srt_keys = sorted(a.keys())
d = OrderedDict()
for k in srt_keys:
d[k] = a[k]
d[k] += b[k]
print d
OrderedDict([(u'Anthracite', [u'3/optimized/8593793_fpx.tif', u'5/optimized/8593795_fpx.tif']), (u'Black', [u'6/optimized/8593796_fpx.tif', u'8/optimized/8593798_fpx.tif']), (u'Cobalt', [u'9/optimized/8593799_fpx.tif', u'1/optimized/8593801_fpx.tif']), (u'Fire', [u'2/optimized/8593802_fpx.tif', u'4/optimized/8593804_fpx.tif']), (u'Fuschia', [u'5/optimized/8593805_fpx.tif', u'7/optimized/8593807_fpx.tif']), (u'Iris', [u'8/optimized/8593808_fpx.tif', u'0/optimized/8593810_fpx.tif']), (u'Midnight', [u'1/optimized/8593811_fpx.tif', u'3/optimized/8593813_fpx.tif'])])
How about using OrderedDict with a tuple list to set initial order. and then simply maintaining it.
Check my answer here for nicer dict syntax: Override the {...} notation so i get an OrderedDict() instead of a dict()?
from collections import OrderedDict
#Use an ordered dict, with a tuple list init to maintain initial order
a = OrderedDict([
(u'Anthracite', [u'3/optimized/8593793_fpx.tif']),
(u'Black', [u'6/optimized/8593796_fpx.tif']),
(u'Cobalt', [u'9/optimized/8593799_fpx.tif']),
(u'Fire', [u'2/optimized/8593802_fpx.tif']),
(u'Fuschia', [u'5/optimized/8593805_fpx.tif']),
(u'Iris', [u'8/optimized/8593808_fpx.tif']),
(u'Midnight', [u'1/optimized/8593811_fpx.tif'])
])
#We don't care about b's order
b = {u'Anthracite': [u'5/optimized/8593795_fpx.tif'],
u'Black': [u'8/optimized/8593798_fpx.tif'],
u'Cobalt': [u'1/optimized/8593801_fpx.tif'],
u'Fire': [u'4/optimized/8593804_fpx.tif'],
u'Fuschia': [u'7/optimized/8593807_fpx.tif'],
u'Iris': [u'0/optimized/8593810_fpx.tif'],
u'Midnight': [u'3/optimized/8593813_fpx.tif']}
merge = OrderedDict()
#Since b has the same keys as a(we don't need to care for diffrent keys), but we want a's order
for key in a:
#We insert by order to an OrderedDict so the same order will be maintained
merge[key] = a[key] + b[key]

Python coverting list to dictionary

I am trying to write a function which takes a list of strings containing names and
marks as a parameter. And return a dictionary of (mark, [list of names who got that mark])
Example:
def example(["John,5", "Jessica,5", "Jack,7"]):
Returns:
{'5' : ["John", "Jessica"], '7' : "Jack"}
I find this a tricky problem... How would I solve this using split(',')
This is what I've done so far:
def create_marks_dict(my_list):
dictionary = {}
for name in my_list:
if name not in dictionary:
dictionary[name]
return dictionary
You'll need to use defaultdict from collections to use lists in your dictionary
from collections import defaultdict
def create_marks_dict(my_list):
dictionary = defaultdict(list)
for item in my_list:
name, marks=item.split(',')
dictionary[marks].append(name)
return dictionary
output:
{'5' : ["John", "Jessica"], '7' : "Jack"}
If output of dict is required instead of defaultdict, you can cast dictionary while returning
return dict(dictionary)
You need to use collections.defaultdict:
from collections import defaultdict
marksdict = defaultdict(list)
for entry in ["John,5", "Jessica,5", "Jack,7"]:
name,mark = entry.split(',')
marksdict[mark].append(name)
print marksdict
this is the version that uses plain python dictionary:
def get_dict(nm_list):
d = {}
for n, m in [(name, mark) for (name, mark) in \
tuple([nm.split(',') for nm in nm_list])]:
d[m] = [n] if m not in d else d[m]+[n]
return d
la = ['John,5', 'Jessica,5', 'Jack,7']
d = get_dict(la)
print d
The output is: {'5': ['John', 'Jessica'], '7': ['Jack']}

More concise way to append a value to a dict array-element?

When I want to append a newvalue into Dict under Key, I find myself have to write:
# Dict={}
# Key = ....
# newvalue = ....
if not Key in Dict:
Dict[Key] = [ newvalue ]
else:
Dict[Key].append(newvalue)
It costs four lines of code. Is there a more concise way with python standard library? e.g
Dict.appendkeyvalue(Key, newvalue)
You can use a defaultdict:
from collections import defaultdict
d = defaultdict(list)
d['something'].append(3)
print d['something']
# > [3]
With standard dictionaries, you can use setdefault():
d = {}
d.setdefault("something", []).append(3)
setdefault() here returns d["something"] if it exists, otherwise it creates a new dictionary entry with [] as its value and returns that.

Categories

Resources