I tried to get the all unique pair combinations from a list.
Here is what I have done so far,
import itertools
# Unique Combination Pairs for list of elements
def uniqueCombinations(list_elements):
l = list(itertools.combinations(list_elements, 2))
s = set(l)
# print('actual', len(l), l)
return list(s)
Test Case
sample = ["apple", "orange", "banana", "grapes", "mango"]
uniqueCombinations(sample)
Output
[('apple', 'banana'),
('orange', 'mango'),
('orange', 'grapes'),
('apple', 'grapes'),
('orange', 'banana'),
('apple', 'mango'),
('grapes', 'mango'),
('apple', 'orange'),
('banana', 'mango'),
('banana', 'grapes')]
The input will be unique strings of list. Assume that duplicate elements will not be passed.
Is there a better / more elegant / more accurate way to do this??
1 Answer 1
From itertools.combinations
, emphasis mine:
Return r length subsequences of elements from the input iterable.
The combination tuples are emitted in lexicographic ordering according to the order of the input iterable. So, if the input iterable is sorted, the combination tuples will be produced in sorted order.
Elements are treated as unique based on their position, not on their value. So if the input elements are unique, there will be no repeat values in each combination.
Which means as long as we pass in a collection of unique elements to itertools.combinations
, there will be no duplicate values in the combinations it returns. And if we can assume that the input list will not contain any duplicate elements, we can rewrite the function like so:
import itertools
def unique_combinations(elements: list[str]) -> list[tuple[str, str]]:
"""
Precondition: `elements` does not contain duplicates.
Postcondition: Returns unique combinations of length 2 from `elements`.
>>> unique_combinations(["apple", "orange", "banana"])
[("apple", "orange"), ("apple", "banana"), ("orange", "banana")]
"""
return list(itertools.combinations(elements, 2))
-
\$\begingroup\$ @superbrain True, then in that case we'd need clarification from @Pluviophile on what assumptions can be made about
list_elements
. \$\endgroup\$Setris– Setris2021年03月10日 07:47:38 +00:00Commented Mar 10, 2021 at 7:47 -
\$\begingroup\$ Trying the above code, I'm getting
TypeError: 'type' object is not subscriptable
\$\endgroup\$Pluviophile– Pluviophile2021年03月10日 10:15:02 +00:00Commented Mar 10, 2021 at 10:15 -
\$\begingroup\$ Is that becoz of this part
: list[str] -> list[tuple[str, str]]
?? \$\endgroup\$Pluviophile– Pluviophile2021年03月10日 10:16:09 +00:00Commented Mar 10, 2021 at 10:16 -
\$\begingroup\$ @Pluviophile sounds like you're not running Python 3.9, you can either omit those type hints or use
from typing import List, Tuple
->List[str]
List[Tuple[str, str]]
\$\endgroup\$Setris– Setris2021年03月10日 10:17:32 +00:00Commented Mar 10, 2021 at 10:17 -
1\$\begingroup\$ @superbrain I think the output for
['apple', 'orange', 'apple']
is actually a bug not a feature, with the OP's code. Check here, what do you think? \$\endgroup\$2021年03月10日 10:45:52 +00:00Commented Mar 10, 2021 at 10:45
uniqueCombinations(['apple', 'orange', 'apple'])
returns[('orange', 'apple'), ('apple', 'apple'), ('apple', 'orange')]
. Is this the output you are expecting for this case? \$\endgroup\$list_elements
can contains duplicates. \$\endgroup\$list_elements
you get('banana', 'orange')
but lose('orange', 'banana')
. The challenge is poorly defined. If so why are you duplicating output with['apple', 'orange', 'apple']
? \$\endgroup\$