Easy way to find what item repeated in list - python

So I have list like
l = [1,2,3,4,4]
If I make a set obvilously I will get
([1,2,3,4])
I need a way to find what item repeated in list and was popped out and I do not want to use looping.
If there is an easy way to do so?
I'm using python 2.7

You'll have to iterate the list, explicitly or implicitly. One way using standard libraries would be with collections.Counter:
In [1]: from collections import Counter
In [2]: l = [1,2,3,4,4]
In [3]: Counter(l).most_common(1)[0][0]
Out[3]: 4
A Counter object is a dictionary with elements of some iterable as keys and their respective counts as values:
In [4]: Counter(l)
Out[4]: Counter({4: 2, 1: 1, 2: 1, 3: 1})
Its most_common() method returns a list of items with highest counts:
In [5]: Counter(l).most_common()
Out[5]: [(4, 2), (1, 1), (2, 1), (3, 1)]
The optional argument restricts the length of the returned list:
In [6]: Counter(l).most_common(1)
Out[6]: [(4, 2)]

Related

Access individual elements of tuples of dictionary keys

Considering the code snippet below -
list1 = [1,2,3,4]
list2 = [1,2,3,4]
list3 = ['a','b','c','d']
dct = dict(zip(zip(list1,list2),list3))
print(dct)
gives me,
{(1, 1): 'a', (2, 2): 'b', (3, 3): 'c', (4, 4): 'd'}
Now,
print(dct.keys())
gives me,
dict_keys([(1, 1), (2, 2), (3, 3), (4, 4)])
How can i access first element of the above list of keys?
Something like -
dct.keys[0, 0] = 1
dct.keys[0, 1] = 1
dct.keys[1, 0] = 2
dct.keys[1, 2] = 2
and so on...
Remember that a dict is unordered, and that dict.keys() may change order.
That said, to access the first element of a list, as you said, you can use list[element_index]. If the elemnt is an iterable, do that again!
So it would be
dct_keys = list(yourdict.keys())
dct_keys[0][0] = 1
dct_keys[0][1] = 1
dct_keys[1][0] = 2
dct_keys[1][1] = 2
You need to first convert the dct.keys() output to a list, and then the problem reduces to simple list-of-tuples indexing. To convert your .keys() output to a list, there are multiple available ways (check this out). Personally, I find using list comprehension as one of the simplest and most generic ways:
>>> [key for key in dct.keys()]
[(1, 1), (2, 2), (3, 3), (4, 4)]
And now simply index this list of tuples as:
>>> [key for key in dct.keys()][0][0]
1
Hope that helps.

Get index range of the repetitive elements in the list

Suppose I have a list a = [-1,-1,-1,1,1,1,2,2,2,-1,-1,-1,1,1,1] in python what i want is if there is any built in function in python in which we pass a list and it will return which element are present at what what index ranges for example
>>> index_range(a)
{-1 :'0-2,9-11', 1:'3-5,12-14', 2:'6-8'}
I have tried to use Counter function from collection.Counter library but it only outputs the count of the element.
If there is not any built in function can you please guide me how can i achieve this in my own function not the whole code just a guideline.
You can create your custom function using itertools.groupby and collections.defaultdict to get the range of numbers in the form of list as:
from itertools import groupby
from collections import defaultdict
def index_range(my_list):
my_dict = defaultdict(list)
for i, j in groupby(enumerate(my_list), key=lambda x: x[1]):
index_range, numlist = list(zip(*j))
my_dict[numlist[0]].append((index_range[0], index_range[-1]))
return my_dict
Sample Run:
>>> index_range([-1,-1,-1,1,1,1,2,2,2,-1,-1,-1,1,1,1])
{1: [(3, 5), (12, 14)], 2: [(6, 8)], -1: [(0, 2), (9, 11)]}
In order to get the values as string in your dict, you may either modify the above function, or use the return value of the function in dictionary comprehension as:
>>> result_dict = index_range([-1,-1,-1,1,1,1,2,2,2,-1,-1,-1,1,1,1])
>>> {k: ','.join('{}:{}'.format(*i) for i in v)for k, v in result_dict.items()}
{1: '3:5,12:14', 2: '6:8', -1: '0:2,9:11'}
You can use a dict that uses list items as keys and their indexes as values:
>>> lst = [-1,-1,-1,1,1,1,2,2,2,-1,-1,-1,1,1,1]
>>> indexes = {}
>>> for index, item in enumerate(lst):
... indexes.setdefault(value, []).append(index)
>>> indexes
{1: [3, 4, 5, 12, 13, 14], 2: [6, 7, 8], -1: [0, 1, 2, 9, 10, 11]}
You could then merge the index lists into ranges if that's what you need. I can help you with that too if necessary.

Maintaining the order of the elements in a frozen set

I have a list of tuples, each tuple of which contains one string and two integers. The list looks like this:
x = [('a',1,2), ('b',3,4), ('x',5,6), ('a',2,1)]
The list contains thousands of such tuples. Now if I want to get unique combinations, I can do the frozenset on my list as follows:
y = set(map(frozenset, x))
This gives me the following result:
{frozenset({'a', 2, 1}), frozenset({'x', 5, 6}), frozenset({3, 'b', 4})}
I know that set is an unordered data structure and this is normal case but I want to preserve the order of the elements here so that I can thereafter insert the elements in a pandas dataframe. The dataframe will look like this:
Name Marks1 Marks2
0 a 1 2
1 b 3 4
2 x 5 6
Instead of operating on the set of frozensets directly you could use that only as a helper data-structure - like in the unique_everseen recipe in the itertools section (copied verbatim):
from itertools import filterfalse
def unique_everseen(iterable, key=None):
"List unique elements, preserving order. Remember all elements ever seen."
# unique_everseen('AAAABBBCCDAABBB') --> A B C D
# unique_everseen('ABBCcAD', str.lower) --> A B C D
seen = set()
seen_add = seen.add
if key is None:
for element in filterfalse(seen.__contains__, iterable):
seen_add(element)
yield element
else:
for element in iterable:
k = key(element)
if k not in seen:
seen_add(k)
yield element
Basically this would solve the issue when you use key=frozenset:
>>> x = [('a',1,2), ('b',3,4), ('x',5,6), ('a',2,1)]
>>> list(unique_everseen(x, key=frozenset))
[('a', 1, 2), ('b', 3, 4), ('x', 5, 6)]
This returns the elements as-is and it also maintains the relative order between the elements.
No ordering with frozensets. You can instead create sorted tuples to check for the existence of an item, adding the original if the tuple does not exist in the set:
y = set()
lst = []
for i in x:
t = tuple(sorted(i, key=str)
if t not in y:
y.add(t)
lst.append(i)
print(lst)
# [('a', 1, 2), ('b', 3, 4), ('x', 5, 6)]
The first entry gets preserved.
There are some quite useful functions in NumPy which can help you to solve this problem.
import numpy as np
chrs, indices = np.unique(list(map(lambda x:x[0], x)), return_index=True)
chrs, indices
>> (array(['a', 'b', 'x'],
dtype='<U1'), array([0, 1, 2]))
[x[indices[i]] for i in range(indices.size)]
>> [('a', 1, 2), ('b', 3, 4), ('x', 5, 6)]
You can do it by simple using the zip to maintain the order in the frozenset.
Give this a try pls.
l = ['col1','col2','col3','col4']
>>> frozenset(l)
--> frozenset({'col2', 'col4', 'col3', 'col1'})
>>> frozenset(zip(*zip(l)))
--> frozenset({('col1', 'col2', 'col3', 'col4')})
Taking an example from the question asked:
>>> x = [('a',1,2), ('b',3,4), ('x',5,6), ('a',2,1)]
>>> frozenset(zip(*zip(x)))
--> frozenset({(('a', 1, 2), ('b', 3, 4), ('x', 5, 6), ('a', 2, 1))})

Sort an array of tuples by product in python

I have an array of 3-tuples and I want to sort them in order of decreasing product of the elements of each tuple in Python. So, for example, given the array
[(3,2,3), (2,2,2), (6,4,1)]
since 3*2*3 = 18, 2*2*2 = 8, 6*4*1 = 24, the final result would be
[(6,4,1), (3,2,3), (2,2,2)]
I know how to sort by, for example, the first element of the tuple, but I'm not sure how to tackle this.
Any help would be greatly appreciated. Thanks!
Use the key argument of sorted/list.sort to specify a function for computing the product, and set the reverse argument to True to make the results descending rather than ascending, e.g.:
from operator import mul
print sorted([(3,2,3), (2,2,2), (6,4,1)], key=lambda tup: reduce(mul, tup), reverse=True)
In [176]: L = [(3,2,3), (2,2,2), (6,4,1)]
In [177]: L.sort(key=lambda (a,b,c):a*b*c, reverse=True)
In [178]: L
Out[178]: [(6, 4, 1), (3, 2, 3), (2, 2, 2)]
A simpler solution from my point of view:
a = [(3,2,3), (2,2,2), (6,4,1)]
def f(L):
return L[0]*L[1]*L[2]
print sorted(a, key = f, reverse = True)
key must be a function that returns a value that will be used in order to sort the list
reverse is True because you want it ordered in decreasing order
>>> from operator import mul
>>> input_list = [(3,2,3), (2,2,2), (6,4,1)]
>>> input_list.sort(key=lambda tup: reduce(mul,tup))
>>> print input_list
[(2, 2, 2), (3, 2, 3), (6, 4, 1)]

iterating in a dictionary.. (double iteration) python

I have a dictionary
example: A = {1:'one',2:'two' , 3: 'three}
so what I want is basically like a 2 for loops sort of stuff..
so that I can get the following order..
# 1 2
# 1 3
# 2 3
... and so on if more elements are there
so basically that o(n2) operation.. where we have a loop withing a loop
how do we achieve this in python dictionary.
I am having a hard time figuring that out..
for key in A.keys():
# how do i Access all the other keys..
# do something
Thanks
>>> import itertools as it
>>> A = {1:'one', 2:'two', 3: 'three'}
>>> list(it.combinations(A.keys(), 2))
[(1, 2), (1, 3), (2, 3)]
>>> import itertools
>>> list(itertools.combinations([1, 2, 3], 2))
[(1, 2), (1, 3), (2, 3)]
If you need to iterate over all pairs of keys, you can do it with simple for loops:
>>> d={1:'one',2:'two',3:'three'}
>>> for (x,y) in ((x,y) for x in d for y in d if x!=y):
... print x,y
Edit:
To avoid listing the same pair twice you can use a set to store the pairs before you iterate:
>>> for (x,y) in set(((min(x,y),max(x,y)) for x in d for y in d if x!=y)):
... print x,y
But this is getting a bit unwieldy, I would suggest using itertools.combinations as shown in dstromberg's answer.

Categories

Resources