Removing weights from a dictionary - python

I have written a python program which gives me the following output:
{'D': {('B', 2.0), ('E', 1.0), ('C', 2.0)}, 'E': {('D', 1.0), ('B', 4.0), ('C', 3.0)},
'A': {('B', 1.0), ('C', 5.0)}, 'B': {('A', 1.0), ('D', 2.0), ('E', 4.0)}, 'C': {('E', 3.0),
('A', 5.0), ('D', 2.0)}`}`
These are nodes of a graph and their corresponding weights. I am trying to remove weights from the above output. Can anyone help me with this.? My output should look something like this :
{ "a" : ["b","c"],"b" : ["a", "e","d"],"c" : ["a", "d", "e"],
"d" : ["b","c","e"],"e" : ["b", "c","d"] }

{k:[x for x,_ in v] for k,v in d.items()} # use iteritems() in python 2
Out[32]:
{'A': ['C', 'B'],
'B': ['D', 'A', 'E'],
'C': ['D', 'A', 'E'],
'D': ['E', 'C', 'B'],
'E': ['C', 'B', 'D']}

dic = {'D': {('B', 2.0), ('E', 1.0), ('C', 2.0)},
'E': {('D', 1.0), ('B', 4.0), ('C', 3.0)},
'A': {('B', 1.0), ('C', 5.0)},
'B': {('A', 1.0), ('D', 2.0), ('E', 4.0)},
'C': {('E', 3.0), ('A', 5.0), ('D', 2.0)}}
dic_node = {}
for node in dic:
dic_node.update({node : [nnode for nnode, weigth in dic[node]]})
dic_node_one = {node : [nnode for nnode, weigth in dic[node]] for node in dic}
Out
>>> dic_node_one
{'A': ['C', 'B'],
'B': ['A', 'E', 'D'],
'C': ['A', 'D', 'E'],
'D': ['B', 'E', 'C'],
'E': ['B', 'C', 'D']}
>>> dic_node
{'A': ['C', 'B'],
'B': ['A', 'E', 'D'],
'C': ['A', 'D', 'E'],
'D': ['B', 'E', 'C'],
'E': ['B', 'C', 'D']}

Using dictionary comprehension, see Python Dictionary Comprehension:
from operator import itemgetter
dic = {'D': {('B', 2.0), ('E', 1.0), ('C', 2.0)},
'E': {('D', 1.0), ('B', 4.0), ('C', 3.0)},
'A': {('B', 1.0), ('C', 5.0)},
'B': {('A', 1.0), ('D', 2.0), ('E', 4.0)},
'C': {('E', 3.0), ('A', 5.0), ('D', 2.0)}}
# Simply extracting only the 1st element of the tuple from the key.
print {k:[alpha for alpha, num in v] for k,v in dic.items()}
print
# Extracting only the 1st element and sorting the tuples by its 2nd element, ascending.
print {k:[alpha for alpha, num in sorted(v, key=itemgetter(1))] for k,v in dic.items()}
print
# Extracting only the 1st element and sorting the tuples by its 2nd element, descending.
print {k:[alpha for alpha, num in sorted(v, key=itemgetter(1), reverse=True)] for k,v in dic.items()}
print
# Extracting only the 1st element and sorting by alphabetical order.
print {k:[alpha for alpha, num in sorted(v)] for k,v in dic.items()}
print
# Extracting only the 1st element and sorting by alphabetical order, lower()
print {k.lower():[alpha.lower() for alpha, num in sorted(v)] for k,v in dic.items()}
[out]:
{'A': ['C', 'B'], 'C': ['A', 'D', 'E'], 'B': ['A', 'E', 'D'], 'E': ['B', 'C', 'D'], 'D': ['B', 'E', 'C']}
{'A': ['B', 'C'], 'C': ['D', 'E', 'A'], 'B': ['A', 'D', 'E'], 'E': ['D', 'C', 'B'], 'D': ['E', 'B', 'C']}
{'A': ['C', 'B'], 'C': ['A', 'E', 'D'], 'B': ['E', 'D', 'A'], 'E': ['B', 'C', 'D'], 'D': ['B', 'C', 'E']}
{'A': ['B', 'C'], 'C': ['A', 'D', 'E'], 'B': ['A', 'D', 'E'], 'E': ['B', 'C', 'D'], 'D': ['B', 'C', 'E']}
{'a': ['b', 'c'], 'c': ['a', 'd', 'e'], 'b': ['a', 'd', 'e'], 'e': ['b', 'c', 'd'], 'd': ['b', 'c', 'e']}

Related

How to do selective combination in Python List?

I'm not really sure how to frame my question, but here's a try. I have a list of strings and tuples of strings. I want all combinations such that I pick only one value from each tuple.
It's much easier to demonstrate with an example.
Input:
x = ['a', ('b', 'c'), ('d', 'e'), 'f']
Output:
y = [
['a', 'b', 'd', 'f'],
['a', 'c', 'd', 'f'],
['a', 'b', 'e', 'f'],
['a', 'c', 'e', 'f']
]
Example 2:
Input:
x = ['a', ('b', 'c'), ('d', 'e'), 'f', ('g', 'h')]
Output:
y = [
['a', 'b', 'd', 'f', 'g'],
['a', 'c', 'd', 'f', 'g'],
['a', 'b', 'e', 'f', 'g'],
['a', 'c', 'e', 'f', 'g'],
['a', 'b', 'd', 'f', 'h'],
['a', 'c', 'd', 'f', 'h'],
['a', 'b', 'e', 'f', 'h'],
['a', 'c', 'e', 'f', 'h']
]
x = ['a', ('b', 'c'), ('d', 'e'), 'f', ('g', 'h')]
First normalize your input
x = [tuple(xx) for xx in x if not isinstance(x, tuple)]
Then:
import iterools
list(itertools.product(*x))
In the output your have a list of tuples, it should be very easy to get list of list as you want.
Actually the normalization step is not necessary.

Find elements that appear in more than k sets in python

I am implementing a basic spell-correction system and I have built an inverted index for my domain's language, where every character bigram is mapped to a list of words that contain that bigram.
Now I want to find all words that share more than 3 character bigrams with the given word w. So the main problem is: given a set of lists, how can one efficiently find elements that occur in 3 or more of them?
For example, given sets:
('a', 'b', 'c', 'd') , ('a', 'e', 'f', 'g'), ('e', 'f', 'g', 'h'), ('b', 'c', 'z', 'y'), ('e', 'k', 'a', 'j')
I like to get the output:
('a', 'e')
since a and e have each appeared in more than 3 sets.
I would appreciate your ideas.
Additional to #Ralf. You can use dicts to construct a histogram
someCollection = [('a', 'b', 'c', 'd') , ('a', 'e', 'f', 'g'), ('e', 'f', 'g', 'h'), ('b', 'c', 'z', 'y'), ('e', 'k', 'a', 'j')]
hist = {}
for collection in someCollection:
for member in collection:
hist[member] = hist.get(member, 0) + 1
Hist now is:
{'a': 3,
'b': 2,
'c': 2,
'd': 1,
'e': 3,
'f': 2,
'g': 2,
'h': 1,
'z': 1,
'y': 1,
'k': 1,
'j': 1}
Which can be sorted with sorted(hist.items(), key = lambda x[1]) # sort along values
You could try using collections.Counter:
from collections import Counter
data = [
('a', 'b', 'c', 'd'),
('a', 'e', 'f', 'g'),
('e', 'f', 'g', 'h'),
('b', 'c', 'z', 'y'),
('e', 'k', 'a', 'j'),
]
c = Counter()
for e in data:
c.update(e)
# print(c)
# for k, v in c.items():
# if v >= 3:
# print(k, v)
You get the output by using this (or something similar):
>>> [k for k, v in c.items() if v >= 3]
['a', 'e']

Custom list of lists into dictionary

I have list of lists and I wish to create a dictionary with length of each element as values. I tried the following:
tmp = [['A', 'B', 'E'], ['B', 'E', 'F'], ['A', 'G']]
tab = []
for line in tmp:
tab.append(dict((k, len(tmp)) for k in line))
But it gives the output as:
[{'A': 3, 'B': 3, 'E': 3}, {'B': 3, 'E': 3, 'F': 3}, {'A': 3, 'G': 3}]
What is the modification that I should make to get the output:
{['A', 'B', 'E']:3, ['B', 'E', 'F']:3, ['A', 'G']:2}
Thanks in advance.
AP
You can't use list objects as dictionary keys, they are mutable and unhashable. You can convert them to tuple. Also note that you are looping over each sub list. You can use a generator expression by only looping over the main list:
In [3]: dict((tuple(sub), len(sub)) for sub in tmp)
Out[3]: {('A', 'B', 'E'): 3, ('A', 'G'): 2, ('B', 'E', 'F'): 3}
{tuple(t):len(t) for t in tmp}
Input :
[['A', 'B', 'E'], ['B', 'E', 'F'], ['A', 'G']]
Output :
{('A', 'G'): 2, ('A', 'B', 'E'): 3, ('B', 'E', 'F'): 3}
Dictionnary does not accept list as key, but tuple

Extracting Unique String Combinations from List of List in Python

I'm trying to extract all the unique combinations of strings from a list of lists in Python. For example, in the code below, ['a', 'b','c'] and ['b', 'a', 'c'] are not unique, while ['a', 'b','c'] and ['a', 'e','f'] or ['a', 'b','c'] and ['d', 'e','f'] are unique.
I've tried converting my list of lists to a list of tuples and using sets to compare elements, but all elements are still being returned.
combos = [['a', 'b', 'c'], ['c', 'b', 'a'], ['d', 'e', 'f'], ['c', 'a', 'b'], ['c', 'f', 'b']]
# converting list of list to list of tuples, so they can be converted into a set
combos = [tuple(item) for item in combos]
combos = set(combos)
grouping_list = set()
for combination in combos:
if combination not in grouping_list:
grouping_list.add(combination)
##
print grouping_list
>>> set([('a', 'b', 'c'), ('c', 'a', 'b'), ('d', 'e', 'f'), ('c', 'b', 'a'), ('c', 'f', 'b')])
How about sorting, (and using a Counter)?
from collections import Counter
combos = [['a', 'b', 'c'], ['c', 'b', 'a'], ['d', 'e', 'f'], ['c', 'a', 'b'], ['c', 'f', 'b']]
combos = Counter(tuple(sorted(item)) for item in combos)
print(combos)
returns:
Counter({('a', 'b', 'c'): 3, ('d', 'e', 'f'): 1, ('b', 'c', 'f'): 1})
EDIT: I'm not sure if I'm correctly understanding your question. You can use a Counter to count occurances, or use a set if you're only interested in the resulting sets of items, and not in their uniqueness.
Something like:
combos = set(tuple(sorted(item)) for item in combos)
Simply returns
set([('a', 'b', 'c'), ('d', 'e', 'f'), ('b', 'c', 'f')])
>>> set(tuple(set(combo)) for combo in combos)
{('a', 'c', 'b'), ('c', 'b', 'f'), ('e', 'd', 'f')}
Simple but if we have same elements in the combo, it will return wrong answer. Then, sorting is the way to go as suggested in others.
How about this:
combos = [['a', 'b', 'c'], ['c', 'b', 'a'], ['d', 'e', 'f'], ['c', 'a', 'b'], ['c', 'f', 'b']]
print [list(y) for y in set([''.join(sorted(c)) for c in combos])]

Sorting a list of lists in python alphabetically by "column"

I have a 2d list of characters like
[['J', 'A', 'M', 'E', 'S'],
['F', 'C', 'A', 'A', 'A'],
['F', 'A', 'B', 'B', 'B']]
What is the best way to go about sorting the first list alphabetically, with the proceeding lists following, ie:
[['A', 'E', 'J', 'M', 'S'],
['C', 'A', 'F', 'A', 'A'],
['A', 'B', 'F', 'B', 'B']]
You can use zip():
>>> [list(t) for t in zip(*sorted(zip(*s)))]
[['A', 'E', 'J', 'M', 'S'], ['C', 'A', 'F', 'A', 'A'], ['A', 'B', 'F', 'B', 'B']]
where s is your list of lists.
The other answers demonstrate how it can be done in one line. This answer illustrates how this works:
Given a list, l:
In [1]: l = [['J', 'A', 'M', 'E', 'S'],
...: ['F', 'C', 'A', 'A', 'A'],
...: ['F', 'A', 'B', 'B', 'B']]
Group the columns into tuples, by passing each row into zip():
In [2]: zip(*l)
Out[2]:
[('J', 'F', 'F'),
('A', 'C', 'A'),
('M', 'A', 'B'),
('E', 'A', 'B'),
('S', 'A', 'B')]
Sort this list of tuples:
In [3]: sorted(zip(*l))
Out[3]:
[('A', 'C', 'A'),
('E', 'A', 'B'),
('J', 'F', 'F'),
('M', 'A', 'B'),
('S', 'A', 'B')]
Note that if the first list contains duplicate items then this sort is not a stable sort.
Transpose the list again to get three lists of tuples:
In [4]: zip(*sorted(zip(*l)))
Out[4]:
[('A', 'E', 'J', 'M', 'S'),
('C', 'A', 'F', 'A', 'A'),
('A', 'B', 'F', 'B', 'B')]
Convert the list of tuples back to a list of lists, using a list comprehension:
In [5]: [list(t) for t in zip(*sorted(zip(*l)))]
Out[5]:
[['A', 'E', 'J', 'M', 'S'],
['C', 'A', 'F', 'A', 'A'],
['A', 'B', 'F', 'B', 'B']]
>>> l = [['J', 'A', 'M', 'E', 'S'],
... ['F', 'C', 'A', 'A', 'A'],
... ['F', 'A', 'B', 'B', 'B']]
>>> zip(*sorted(zip(*l)))
[('A', 'E', 'J', 'M', 'S'), ('C', 'A', 'F', 'A', 'A'), ('A', 'B', 'F', 'B', 'B')]
if you need lists in result:
>>> map(list, zip(*sorted(zip(*l))))
[['A', 'E', 'J', 'M', 'S'], ['C', 'A', 'F', 'A', 'A'], ['A', 'B', 'F', 'B', 'B']]

Categories