0

I have a set (any collection type will do for all I care) like this.

myset = {{a},{b},{c},{d,e}, {d,f}}

I am now trying to check whether two elements {a} and {d} exist in myset and if so merge {a} with {d,e}. If on the other hand I am checking {d} and {f}, then I will merge {d,e} and {d,f} to get {d,e,f}.

I will be grateful if any one shows me the direction towards the solution.

Nilesh
  • 20,521
  • 16
  • 92
  • 148
Jermi
  • 13
  • 2
  • 5
    Will you please explain your logic in more detail? What is the logic by selection {a} to add in set if {a} and {d} exits? – Nilesh Nov 25 '14 at 07:33
  • your question is unclear. – salmanwahed Nov 25 '14 at 08:26
  • what would happen in this case: `{{a,b},{a,c},{b,d},{b,e}}` and you are checking for {a} and {b} –  Nov 25 '14 at 08:28
  • I will never have such a set as {{a,b},{a,c},{b,d},{b,e}}. I am building my cluster from a set having {{a},{b},{c},{d}} at the beginning. In the first iteration I may merge {a} and {b} with the resulting output {{ab},{c},{d}}. In the second, I may search for {a} and {c} resulting with {{abc},{d}} – Jermi Nov 25 '14 at 08:35
  • The problem I have basically is, given a set (myset) and two search elements i and j, newmyset = myset - i - j U (i,j) – Jermi Nov 25 '14 at 08:40

4 Answers4

2

This might not be the most pythonic approach but it should work,let me know if it doesn't and I have done it for lists,you could do it for sets using a similar approach

def get_member(a,the_list):
    if a in the_list:
        return a
    else:
        for elem in the_list:
            if isinstance(elem,list):
                if a in elem:
                    return elem
    return None

def merge_member(a,b,the_list):
    get_member_a = get_member(a,the_list)
    get_member_b = get_member(b,the_list)
    if get_member_a and get_member_b:
        the_list.remove(get_member_a)
        the_list.remove(get_member_b)
        if isinstance(get_member_b,list):
            get_member_b.extend(get_member_a)
            the_list.append(get_member_b)
        elif isinstance(get_member_a,list):
            get_member_a.extend(get_member_b)
            the_list.append(get_member_a)
        else:
            the_list.append([get_member_b,get_member_a])
    return the_list
  • This worked fine for me. Changing it to a set is a problem however as python sets do not accept [unhashable] sets or lists as elements. Anyways, I have at least a solution for the problemat hand. – Jermi Nov 26 '14 at 10:19
  • Yep,you'll have to use frozensets,though I think you already knew that. –  Nov 26 '14 at 10:25
2

First of all: you cannot build a set of sets in python, as a set needs to contain hashable values while a set itself is not hashable.

But of course you could do the same with a list of of sets. The probably fastest and most pythonic solution should be like:

myset = [{1}, {2}, {3}, {4, 5}, {5, 6}]
merged_set = set().union(*myset)

(set.union cannot only be used with one parameter, but with any number of parameters)

mrh1997
  • 922
  • 7
  • 18
0

I appears that we need to improve the merge_member block to handle such cases where we have [['a'],['b'],['c'],['d'],['e','f','g']], as the_list and we are looking for 'e' and 'f'.

def merge_member(a,b,the_list):
    get_member_a = get_member(a, the_list)
    get_member_b = get_member(b, the_list)
    if get_member_a and get_member_b:
        if get_member_a.__eq__(get_member_b):
           the_list.remove(get_member_a)
           if isinstance(get_member_b, list):
              the_list.append(get_member_b)
        else:
           the_list.remove(get_member_a)
           the_list.remove(get_member_b)
           if isinstance(get_member_b, list):
              get_member_b.extend(get_member_a)
              the_list.append(get_member_b)
           elif isinstance(get_member_a, list):
              get_member_a.extend(get_member_b)
              the_list.append(get_member_a)
           else:
              the_list.append([get_member_b,get_member_a])
    return the_list
Jermi
  • 13
  • 2
0

You can use this method to merge a set list:

from functools import reduce # for python3
myset = [{'a'}, {'b'}, {'c'}, {'d','e'}, {'d','f'}] 
reduce(lambda x, y: {*x, *y}, myset)

output:

{'a', 'b', 'c', 'd', 'e', 'f'}

Solution for the question:

from functools import reduce # for python3
myset = [{'a'}, {'b'}, {'c'}, {'d','e'}, {'d','f'}]  # define your set list

def get_element_set(elem, myset):
    try:
        z = [x for x in myset if elem in x] 
        result = reduce(lambda x, y: {*x, *y}, z)
        return result
    except TypeError as e:
        print('Element "%s" is not exist in myset!' % elem)
        return {}

def merge_member(elem_list, myset):
    z = map(lambda elem: get_element_set(elem, myset), elem_list)
    result = reduce(lambda x, y: {*x, *y}, z)
    return result

Example:

get_element_set('d', myset) # {'d', 'e', 'f'}
get_element_set('g', myset) # Element "g" is not exist in myset! {}
merge_member(['f', 'd'], myset) # {'d', 'e', 'f'}
merge_member(['a', 'd'], myset) # {'a', 'd', 'e', 'f'}
Ferris
  • 5,325
  • 1
  • 14
  • 23