1

Here i have list

some_list = [('A','B','IP1','N1'),('A','B','IP3','N3'),('B','C','IP2','N2'),('B','C','IP3','N3'),('D','F','IP4','N4')]

for suppose 'A','B' is in ('A','B','IP1','N1'),('A','B','IP3','N3') then we need to combine both tuple and make as one tuple and replace ('A','B','IP1','N1'),('A','B','IP3','N3') with ('A','B','IP1','N1','IP3','N3') in some_list

Result:

some_list = [('A','B','IP1','N1','IP3','N3'), ('B','C','IP2','N2','IP3','N3'), ]

should come but make sure instead of 'A', 'B','C',.. what ever it'll not be same for everytime

Can you help me with that?

Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343
smily dips
  • 65
  • 8
  • Just install `ordered-set`, check https://pypi.org/project/ordered-set/. After that you can try `some_list = [tuple(set(some_list[i] + some_list[i + 1])) for i in range(0, len(some_list) - 1, 2)]` to get the result. I have written this in the answer where you can see the differences with `set()` and `OrderedSet()`. – hygull Nov 18 '18 at 16:45

3 Answers3

2

basically you need to create a tuple key for your 2 values, and create a default dictionary with that.

Extend the rest of the list for each key, and transform back the key/value couple to list of lists by adding the key (as list) to the value

like this:

import collections

some_list = [('A','B','IP1','N1'),('A','B','IP3','N3'),('B','C','IP2','N2'),('B','C','IP3','N3'),('D','F','IP4','N4')]

c = collections.defaultdict(list)
for k1,k2,*b in some_list:   # extended iterable unpacking allows this
    c[(k1,k2)].extend(b)  # add to existing list or create a new one

result = [a+tuple(b) for a,b in c.items()]

result:

>>> result
[('D', 'F', 'IP4', 'N4'),
 ('B', 'C', 'IP2', 'N2', 'IP3', 'N3'),
 ('A', 'B', 'IP1', 'N1', 'IP3', 'N3')]

The for k1,k2,*b in some_list part allows to put the 2 first values in separate k1 and k2 variables, and the "rest" in a b list. This feature isn't available in python 2. Python 2 users can replace the loop by a more basic:

for a in some_list:
    c[tuple(a[:2])].extend(a[2:])  # add to existing list or create a new one

(this problem is similar to that one: Merge tuples with the same key for the core part, but the pre/post processing makes it different)

Jean-François Fabre
  • 137,073
  • 23
  • 153
  • 219
0

You can also use itertools.groupby() to group the tuples by the first two items, then combine the rest of the tuple at the end with flattening:

from itertools import groupby
from itertools import chain
from pprint import pprint


some_list = [
    ("A", "B", "IP1", "N1"),
    ("A", "B", "IP3", "N3"),
    ("B", "C", "IP2", "N2"),
    ("B", "C", "IP3", "N3"),
    ("D", "F", "IP4", "N4"),
]

# key -> first two, rest -> everything after first two
key, rest = lambda x: x[:2], lambda x: x[2:]

pprint(
    [
        list(chain.from_iterable((k, *tuple(map(rest, g)))))
        for k, g in groupby(sorted(some_list, key=key), key=key)
    ]
)

Which gives the following:

[['A', 'B', 'IP1', 'N1', 'IP3', 'N3'],
 ['B', 'C', 'IP2', 'N2', 'IP3', 'N3'],
 ['D', 'F', 'IP4', 'N4']]

The above uses itertools.chain.from_iterable() to flatten the grouped tuple of tuples. You also need to sort the list of tuples by the first two items, in order to group them with itertools.groupby(). This is because it groups by consecutive keys in an iterable, which you can only achieve by sorting.

Additionally, If your list of tuples are always of length 4 and the key is always the first two items, you can also use operater.itemgetter() for key and rest:

from operator import itemgetter
key, rest = itemgetter(0, 1), itemgetter(2, 3)

Which looks up the first two values (0, 1) and last two values (2, 3).

RoadRunner
  • 25,803
  • 6
  • 42
  • 75
0

You can also try below code.

>>> def get_combined_items(tup1, tup2):
...     l = list(tup1)
...     for item in tup2:
...         if item not in l:
...             l.append(item)
...     return l
...
>>>
>>> if len(some_list) % 2 == 0: # even number of items
...     some_list = [tuple(get_combined_items(some_list[i], some_list[i + 1])) for i in range(0, len(some_list) - 1, 2)]
... else:
...     last_item = some_list[-1] # save last item
...     some_list = [tuple(get_combined_items(some_list[i], some_list[i + 1])) for i in range(0, len(some_list) - 1, 2)]
...     some_list = some_list + [last_item]
...
>>> some_list
[('A', 'B', 'IP1', 'N1', 'IP3', 'N3'), ('B', 'C', 'IP2', 'N2', 'IP3', 'N3'), ('D', 'F', 'IP4', 'N4')]
>>>

And if you want to try 3rd party package then install ordered-set using pip install ordered-set.

» pip install ordered-set

You can check https://pypi.org/project/ordered-set/.

Note: This is just to keep the elements in order after passing the combined tuple to set().

>>> from ordered_set import OrderedSet
>>>
>>> some_list = [('A','B','IP1','N1'),('A','B','IP3','N3'),('B','C','IP2','N2'),('B','C','IP3','N3'),('D','F','IP4','N4')]
>>>
>>> if len(some_list) % 2 == 0: # even number of items
...     some_list = [tuple(OrderedSet(some_list[i] + some_list[i + 1])) for i in range(0, len(some_list) - 1, 2)]
... else:
...     last_item = some_list[-1] # save last item
...     some_list = [tuple(OrderedSet(some_list[i] + some_list[i + 1])) for i in range(0, len(some_list) - 1, 2)]
...     some_list = some_list + [last_item]
...
>>>
>>> some_list
[('A', 'B', 'IP1', 'N1', 'IP3', 'N3'), ('B', 'C', 'IP2', 'N2', 'IP3', 'N3'), ('D', 'F', 'IP4', 'N4')]
>>>
hygull
  • 8,464
  • 2
  • 43
  • 52
  • In Input there is also ('D','F','IP4','N4') which is missing in your result – smily dips Nov 18 '18 at 16:59
  • As I understood, you want to loop through 2 items in each iteration. So, what should be the final answer in this case. Just paste, I will fix and update my answer. I saw, it is also missing in your question, the `result` value. – hygull Nov 18 '18 at 17:09
  • some_list_input = [('A','B','IP1','N1'),('A','B','IP3','N3'),('B','C','IP2','N2'),('B','C','IP3','N3'),('D','F','IP4','N4')] and my output list should be [('A', 'B', 'IP1', 'N1', 'IP3', 'N3'), ('B', 'C', 'IP2', 'N2', 'IP3', 'N3'), ('D','F','IP4','N4')] and index shouldn't change and i shouldn't install any outside packages only i need to use inbuilt packages – smily dips Nov 18 '18 at 17:20
  • Okay, got, thanks for reply & now I have updated my answer, you can check. – hygull Nov 18 '18 at 17:32
  • Sorry as I have mentioned that I shouldn't install any outside packages only python inbuilt packages need to be used – smily dips Nov 18 '18 at 17:35
  • @smily, I've updated my answer, you can check. Thanks for replying with new update. – hygull Nov 18 '18 at 17:56
  • Thanks it is working but i don't want to use for loops much because i have huge data, but its ok i have done it – smily dips Nov 18 '18 at 18:07
  • Can you please check this question also?https://stackoverflow.com/questions/53363521/need-to-avoid-nested-for-loop-as-it-is-repeating-70007000-times-for-7000-rows?noredirect=1#comment93603732_53363521 – smily dips Nov 18 '18 at 18:08
  • The link does not exist. – hygull Nov 19 '18 at 03:55