Group list elements into tuples by index - python

I have a list like [1,2,3,1,2,3,1,2,3] and I would like to group the common elements by their index so the result would be: [(0,3,6),(1,4,7),...]

Use a dictionary; collections.defaultdict() would be easiest:
from collections import defaultdict
indices = defaultdict(list)
for index, value in enumerate(inputlist):
indices[value].append(index)
result = [tuple(indices[value]) for value in sorted(indices)]
This assumes that you wanted the indices ordered by value sort order.

If order matters then use collections.OrderedDict otherwise go for collections.defaultdict:
>>> from collections import OrderedDict
>>> lis = [1,2,3,1,2,3,1,2,3]
>>> d = OrderedDict()
>>> for i, item in enumerate(lis):
d.setdefault(item, []).append(i)
...
>>> d.values()
[[0, 3, 6], [1, 4, 7], [2, 5, 8]]

Related

How do I append multiple lists to one key in a python dictionary?

I want to append values to a key in a dictionary, where the values are actually lists. There could be one list, or there could be multiple lists.
The current way I'm trying to do it, the new list I try to add on just overwrites the last list. As far as I can tell, I can't append a list to a dict like so either:
my_dict.append(my_list))
Current code that overwrites each other:
urls[domain] = [uri, datecreated]
Is this possible? If so, how?
Sample results would look like this
print all keys and values in urls{}:
google.com : ['/helloworld', 2010-04-02], ['/apage/anotherpage', 2015-09-12]
microsoft.com : ['/awebpage', 2009-02-01], ['/bananas', 2015-12-24], ['/anothergreaturi', 205-12-10]
You can have each dictionary entry a list, so you append to that list.
>>> a = Linter("ahahah")
>>> a.write_file()
>>> a = dict()
>>> a["first"] = []
>>> a["first"].append([1,2,3])
>>> a["first"].append([4,5,6])
>>> a["second"] = []
>>> a["second"].append([7,8,9])
>>> a
{
'second':[
[7, 8, 9]
],
'first': [
[1, 2, 3],
[4, 5, 6]
]
}
but honestly, at some point just consider using classes?
Is this what you are trying to achieve?
>>> d={'a': ['b']}
>>> d['a']
['b']
>>> d['a'] += ['c']
>>> d['a']
['b', 'c']
You can use a defaultdict to accomplish what you need.
from collections import defaultdict
my_dict = defaultdict(list)
my_dict[1].append([1,2])
my_dict[1].append([3,4])
my_dict[2].append([8,9])
Now you can access each key element as you would access a dictionary
>>> my_dict[1]
[[1, 2], [3, 4]]
>>> for k, v in my_dict.iteritems():
print k,v
1 [[1, 2], [3, 4]]
2 [[8, 9]]
class My_Dictionary(dict):
def __init__(self):
self = dict()
def add(self, key, value):
try:
self[key].append(value)
except KeyError:
self[key] = [value]
if __name__ == '__main__':
dict_obj = My_Dictionary()
key = 0
take_1 = [1,6,2,4]
take_2 = [7,3,5,6]
dict_obj.add(key, take_1)
dict_obj.add(key, take_2)
print(dict_obj)
This code will return a dictionary in your desired format.
{0: [[1, 6, 2, 4], [7, 3, 5, 6]]}

Find multiple occuring string in array and output index

I have a array filled with e-mail addresses which change constantly. e.g.
mailAddressList = ['chip#plastroltech.com','spammer#example.test','webdude#plastroltech.com','spammer#example.test','spammer#example.test','support#plastroltech.com']
How do I find multiple occurrences of the same string in the array and output it's indexes?
just group indexes by email and print only those items, where lenght of index list is greater than 1:
from collections import defaultdict
mailAddressList = ['chip#plastroltech.com',
'spammer#example.test',
'webdude#plastroltech.com',
'spammer#example.test',
'spammer#example.test',
'support#plastroltech.com'
]
index = defaultdict(list)
for i, email in enumerate(mailAddressList):
index[email].append(i)
print [(email, positions) for email, positions in index.items()
if len(positions) > 1]
# [('spammer#example.test', [1, 3, 4])]
Try this:
query = 'spammer#example.test''
indexes = [i for i, x in enumerate(mailAddressList) if x == query]
Output:
[1, 3, 4]
In [7]: import collections
In [8]: q=collections.Counter(mailAddressList).most_common()
In [9]: indexes = [i for i, x in enumerate(mailAddressList) if x == q[0][0]]
In [10]: indexes
Out[10]: [1, 3, 4]
note: solutions submitted before are more pythonic than mine. but in my opinon, lines that i've written before are easier to understand. i simply will create a dictionary, then will add mail adresses as key and the indexes as value.
first declare an empty dictionary.
>>> dct = {}
then iterate over mail adresses (m) and their indexes (i) in mailAddressList and add them to dictionary.
>>> for i, m in enumerate(mailAddressList):
... if m not in dct.keys():
... dct[m]=[i]
... else:
... dct[m].append(i)
...
now, dct looks liike this.
>>> dct
{'support#plastroltech.com': [5], 'webdude#plastroltech.com': [2],
'chip#plastroltech.com': [0], 'spammer#example.test': [1, 3, 4]}
there are many ways to grab the [1,3,4]. one of them (also not so pythonic :) )
>>> [i for i in dct.values() if len(i)>1][0]
[1, 3, 4]
or this
>>> [i for i in dct.items() if len(i[1])>1][0] #you can add [1] to get [1,3,4]
('spammer#example.test', [1, 3, 4])
Here's a dictionary comprehension solution:
result = { i: [ k[0] for k in list(enumerate(mailAddressList)) if k[1] == i ] for j, i in list(enumerate(mailAddressList)) }
# Gives you: {'webdude#plastroltech.com': [2], 'support#plastroltech.com': [5], 'spammer#example.test': [1, 3, 4], 'chip#plastroltech.com': [0]}
It's not ordered, of course, since it's a hash table. If you want to order it, you can use the OrderedDict collection. For instance, like so:
from collections import OrderedDict
final = OrderedDict(sorted(result.items(), key=lambda t: t[0]))
# Gives you: OrderedDict([('chip#plastroltech.com', [0]), ('spammer#example.test', [1, 3, 4]), ('support#plastroltech.com', [5]), ('webdude#plastroltech.com', [2])])
This discussion is less relevant, but it might also prove useful to you.
mailAddressList = ["chip#plastroltech.com","spammer#example.test","webdude#plastroltech.com","spammer#example.test","spammer#example.test","support#plastroltech.com"]
print [index for index, address in enumerate(mailAddressList) if mailAddressList.count(address) > 1]
prints [1, 3, 4], the indices of the addresses occuring more than once in the list.

Intersection of subelements of multiple list of lists in dictionary

I have a number of lists of lists stored in a dictionary. I want to find the intersection of the sub-lists (i.e. intersection of dict[i][j]) for all keys of the dictionary. )
For example, if the dictionary stored sets of tuples instead, I could use the code:
set.intersection(*[index[key] for key in all_keys])
What is an efficient way to do this? One way I tried was to first convert each list of lists into a set of tuples and then taking the intersection of those, but this is rather clunky.
Example:
Suppose the dictionary of lists of lists is
dict = {}
dict['A'] = [[1, 'charlie'], [2, 'frankie']]
dict['B'] = [[1, 'charlie'], [2, 'chuck']]
dict['C'] = [[2, 'chuck'], [1, 'charlie']]
then I want to return
[1, 'charlie']
(maybe as a tuple, doesn't have to be list)
EDIT: I just found an okay way to do it, but it's not very 'pythonic'
def search(index, search_words):
rv = {tuple(t) for t in index[search_words[0]]}
for word in search_words:
rv = rv.intersection({tuple(t) for t in index[word]})
return rv
Let's call your dictionary of lists of lists d:
>>> d = {'A': [[1, 'charlie'], [2, 'frankie']], 'B': [[1, 'charlie'], [2, 'chuck']], 'C': [[2, 'chuck'], [1, 'charlie']]}
I am calling it d because dict is a builtin and we would prefer not to overwrite it.
Now, find the intersection:
>>> set.intersection( *[ set(tuple(x) for x in d[k]) for k in d ] )
set([(1, 'charlie')])
How it works
set(tuple(x) for x in d[k])
For key k, this forms a set out of tuples of the elements in d[k]. Taking k='A' for example:
>>> k='A'; set(tuple(x) for x in d[k])
set([(2, 'frankie'), (1, 'charlie')])
[ set(tuple(x) for x in d[k]) for k in d ]
This makes a list of the sets from the step above. Thus:
>>> [ set(tuple(x) for x in d[k]) for k in d ]
[set([(2, 'frankie'), (1, 'charlie')]),
set([(2, 'chuck'), (1, 'charlie')]),
set([(2, 'chuck'), (1, 'charlie')])]
set.intersection( *[ set(tuple(x) for x in d[k]) for k in d ] )
This gathers the intersection of the three sets as above:
>>>set.intersection( *[ set(tuple(x) for x in d[k]) for k in d ] )
set([(1, 'charlie')])
[item for item in A if item in B+C]
Your usecase demands the use of reduce function. But, quoting the BDFL's take on reduce,
So now reduce(). This is actually the one I've always hated most, because, apart from a few examples involving + or *, almost every time I see a reduce() call with a non-trivial function argument, I need to grab pen and paper to diagram what's actually being fed into that function before I understand what the reduce() is supposed to do. So in my mind, the applicability of reduce() is pretty much limited to associative operators, and in all other cases it's better to write out the accumulation loop explicitly.
So, what you have got is already 'pythonic'.
I would write the program like this
>>> d = {'A': [[1, 'charlie'], [2, 'frankie']],
... 'B': [[1, 'charlie'], [2, 'chuck']],
... 'C': [[2, 'chuck'], [1, 'charlie']]}
>>> values = (value for value in d.values())
>>> result = {tuple(item) for item in next(values)}
>>> for item in values:
... result &= frozenset(tuple(items) for items in item)
>>> result
set([(1, 'charlie')])
from collections import defaultdict
d = {'A': [[1, 'charlie'], [2, 'frankie']], 'B': [[1, 'charlie'], [2, 'chuck']], 'C': [[2, 'chuck'], [1, 'charlie']]}
frequency = defaultdict(set)
for key, items in d.iteritems():
for pair in items:
frequency[tuple(pair)].add(key)
output = [
pair for pair, occurrances in frequency.iteritems() if len(d) == len(occurrances)
]
print output

How to add values in keys in a dictionary inside a loop?

I have the following list:
x=['a','3','4','b','1','2','c','4','5']
How can i make the following dictionary:
b = {'a':[3,4],'b':[1,2],'c':[4,5]}
I tried the following:
Category = defaultdict(int)
for i in a:
if Varius.is_number(i)==False:
Category[i]=[]
keys.append(i)
else:
Category[keys(i)] = i
The keys are created but after i have problem to insert the values.(is_number is a function which check if the value of the list is number or string).First day away of MATLAB.First day in Python..
Here an example that actually uses the feature that defaultdict provides over the normal dict:
from collections import defaultdict
x=['a','3','4','b','1','2','c','4','5']
key='<unknown>' # needed if the first value of x is a number
category = defaultdict(list) # defaultdict with list
for i in x:
if i.isalpha():
key = i;
else:
category[key].append(i) # no need to initialize with an empty list
print category
Also: you should use lower case names for class instances. Uppercase names are usually reserved for classes. Read pep8 for a style guide.
If the key/value entries in your list x are evenly spaced, here's an alternative way to build the dictionary. It uses a few of Python's built in features and functions:
>>> keys = x[::3]
>>> values = [map(int, pair) for pair in zip(x[1::3], x[2::3])]
>>> dict(zip(keys, values))
{'a': [3, 4], 'b': [1, 2], 'c': [4, 5]}
To explain what's being used here:
list slicing to create new lists from x: x[start:stop:step]
here zip takes two lists and makes a list of tuples containing the n-th elements of each list
map(int, pair) turns a tuple of digit strings into a list of integers
values is constructed with list comprehension - the map function is applied to each pair
dict turns a list of pairs into dictionary keys/values
You can use itertools.groupby :
>>> from itertools import groupby
>>> l=[list(g) for k,g in groupby(x,lambda x : x.isalpha())]
>>> p=[l[i:i+2] for i in range(0,len(l),2)]
>>> {i[0]:map(int,j) for i,j in p}
{'a': [3, 4], 'c': [4, 5], 'b': [1, 2]}
Assuming you have a key on the first positions of your list (x) and that after a letter, there will be a number:
from collections import defaultdict
x=['a','3','4','b','1','2','c','4','5']
key = x[0]
Category = defaultdict(int)
for i in x:
if i.isalpha():
key = i;
else:
Category[key].append(i)
print Category
Using itertools.groupby and some iterator stuff:
>>> from itertools import groupby
>>> it = (next(g) if k else map(int, g) for k, g in groupby(x, str.isalpha))
>>> {k: next(it) for k in it}
{'a': [3, 4], 'c': [4, 5], 'b': [1, 2]}
Here the first iterator will yield something like:
>>> [next(g) if k else map(int, g) for k, g in groupby(x, str.isalpha)]
['a', [3, 4], 'b', [1, 2], 'c', [4, 5]]
Now as this iterator is going to yield key-value alternately, we can loop over this iterator and get the next item from it(i.e the value) using next()
>>> it = (next(g) if k else map(int, g) for k, g in groupby(x, str.isalpha))
>>> for k in it:
print k,'-->' ,next(it)
...
a --> [3, 4]
b --> [1, 2]
c --> [4, 5]
There's another way to consume this iterator that is using zip, but it's a little hard to understand IMO:
>>> it = (next(g) if k else map(int, g) for k, g in groupby(x, str.isalpha))
>>> dict(zip(*[it]*2))
{'a': [3, 4], 'c': [4, 5], 'b': [1, 2]}
Simple solution using just dict and list:
>>> category = {}
>>> for i in x:
... if i.isalpha():
... items = category[i] = []
... elif category:
... items.append(i)
...
>>> print(category)
{'c': ['4', '5'], 'a': ['3', '4'], 'b': ['1', '2']}

How do I remove duplicate arrays in a list in Python

I have a list in Python filled with arrays.
([4,1,2],[1,2,3],[4,1,2])
How do I remove the duplicate array?
Very simple way to remove duplicates (if you're okay with converting to tuples/other hashable item) is to use a set as an intermediate element.
lst = ([4,1,2],[1,2,3],[4,1,2])
# convert to tuples
tupled_lst = set(map(tuple, lst))
lst = map(list, tupled_lst)
If you have to preserve order or don't want to convert to tuple, you can use a set to check if you've seen the item before and then iterate through, i.e.,
seen = set()
def unique_generator(lst)
for item in lst:
tupled = tuple(item)
if tupled not in seen:
seen.add(tupled)
yield item
lst = list(unique_generator(lst))
This isn't great python, but you can write this as a crazy list comprehension too :)
seen = set()
lst = [item for item in lst if not(tuple(item) in seen or seen.add(tuple(item)))]
If order matters:
>>> from collections import OrderedDict
>>> items = ([4,1,2],[1,2,3],[4,1,2])
>>> OrderedDict((tuple(x), x) for x in items).values()
[[4, 1, 2], [1, 2, 3]]
Else it is much simpler:
>>> set(map(tuple, items))
set([(4, 1, 2), (1, 2, 3)])
l = ([4,1,2],[1,2,3],[4,1,2])
uniq = []
for i in l:
if not i in uniq:
uniq.append(i)
print('l=%s' % str(l))
print('uniq=%s' % str(uniq))
which produces:
l=([4, 1, 2], [1, 2, 3], [4, 1, 2])
uniq=[[4, 1, 2], [1, 2, 3]]
Use sets to keep track of seen items, but as sets can only contain hashable items so you may have to convert the items of your tuple to some hashable value first( tuple in this case) .
Sets provide O(1) lookup, so overall complexity is going to be O(N)
This generator function will preserve the order:
def solve(lis):
seen = set()
for x in lis:
if tuple(x) not in seen:
yield x
seen.add(tuple(x))
>>> tuple( solve(([4,1,2],[1,2,3],[4,1,2])) )
([4, 1, 2], [1, 2, 3])
If the order doesn't matter then you can simply use set() here:
>>> lis = ([4,1,2],[1,2,3],[4,1,2]) # this contains mutable/unhashable items
>>> set( tuple(x) for x in lis) # apply tuple() to each item, to make them hashable
set([(4, 1, 2), (1, 2, 3)]) # sets don't preserve order
>>> lis = [1, 2, 2, 4, 1] #list with immutable/hashable items
>>> set(lis)
set([1, 2, 4])

Categories

Resources