set operations on sets with more than one of the same member

  • (3 Pages)
  • +
  • 1
  • 2
  • 3

38 Replies - 2015 Views - Last Post: 13 March 2018 - 01:54 PM Rate Topic: -----

#1 bobsmith76   User is offline

  • D.I.C Head

Reputation: 9
  • View blog
  • Posts: 211
  • Joined: 14-February 17

set operations on sets with more than one of the same member

Posted 07 March 2018 - 12:42 PM

I simply love Python's set operations. These things make life so much easier. In any case, one of the problem I'm having is what to do when you have a list where it's important how many times the same member repeats itself. For example, I'm going to be doing this operation a lot where I have to determine if one list is in another list. Below list 2 is not in list1 because list2 has the number 3 twice. You can't convert list1 and list2 into sets because the fact that there are two 3's is important. The best way I came up with to determine whether or not list2 is not in list1 is to use remove. But I would eventually have to use the deepcopy method because I'm going to be using list1 several times and the remove method mutates it. Plus the method I used is 5 lines which is too many in my book. The best work around I came up with is below that with set1 and set2. For those strings that repeat themselves I just make them unique with a number. Does anyone know of a better method because even method 2 is slightly long winded.



list1 = [1, 2, 3, 4, 5]
list2 = [5, 3, 3]

try:
    for x in list2: list1.remove(x)
    bool1 = True
except:
    bool1 = False

set1 = {'Hs', "Ho", "Ho1", "Lo"}
set2 = {"Ho", "Ho1", "Lo", "Ms", "Ns", "Hs"}

if len(set1 - set2) == 0:
    bool1 = True
else:
    bool1 = False




Is This A Good Question/Topic? 0
  • +

Replies To: set operations on sets with more than one of the same member

#2 ndc85430   User is online

  • I think you'll find it's "Dr"
  • member icon

Reputation: 824
  • View blog
  • Posts: 3,335
  • Joined: 13-June 14

Re: set operations on sets with more than one of the same member

Posted 07 March 2018 - 12:53 PM

View Postbobsmith76, on 07 March 2018 - 07:42 PM, said:

Plus the method I used is 5 lines which is too many in my book.


I'm extremely tired right now, so probably can't give much input on the main question, but this is concerning. Why are 5 lines too many? I'd think a function having that many lines is perfectly readable, assuming the complexity of those lines is very low. Why obsess about making things as short as possible? That's going to hurt readability.
Was This Post Helpful? 0
  • +
  • -

#3 DK3250   User is offline

  • Pythonian
  • member icon

Reputation: 406
  • View blog
  • Posts: 1,312
  • Joined: 27-December 13

Re: set operations on sets with more than one of the same member

Posted 08 March 2018 - 10:46 AM

You have a strange habit of showing working code and then ask for shorter versions. But shorter does not necessarily mean better.

In your first code snippet you use a try-except block to catch a ValueError exception (x not in list). I my world try-except should not be used if a simple if-statement can do it:
list1 = [1, 2, 3, 4, 5]
list2 = [5, 3, 3]

def sub_lst(list1, list2):
    lst = list1.copy()
    for x in list2:
        if x in lst:  # this makes the try-except block obsolete
            lst.remove(x)
        else:
            return False
    return True

print(sub_lst(list1, list2))
Not shorter, but (in my opinion) better..!

Your question leads me to think of the library 'collections'.
As you are a fully adequate programmer yourself, I will just leave a link and let it be up to you if this is a path to pursue.
Link: https://www.w3resour...exercise-30.php

This post has been edited by DK3250: 08 March 2018 - 10:49 AM

Was This Post Helpful? 0
  • +
  • -

#4 DK3250   User is offline

  • Pythonian
  • member icon

Reputation: 406
  • View blog
  • Posts: 1,312
  • Joined: 27-December 13

Re: set operations on sets with more than one of the same member

Posted 08 March 2018 - 11:18 AM

Oh, your second code snippet (with sets) is unclear.
It will return 'True', but set2 is not a subset of set1.
Or, maybe, I've misunderstood your intentions...?
Was This Post Helpful? 0
  • +
  • -

#5 jon.kiparsky   User is online

  • Beginner
  • member icon


Reputation: 11069
  • View blog
  • Posts: 18,906
  • Joined: 19-March 11

Re: set operations on sets with more than one of the same member

Posted 08 March 2018 - 11:27 AM

If you want to represent a "multiset", you might consider using a Counter as your starting point.
>>> from collections import Counter
>>> counts = Counter([1,2,2,3,3,3,4,4,4,"five", "five"])
>>> counts
>>> other_counts = Counter([1,1,2,"six"])
>>> other_counts
Counter({1: 2, 2: 1, 'six': 1})
>>> 



Clearly you could then say that a union of those two "sets" would look like Counter({3: 3, 4: 3, 'five': 2, 'six': 1, 2: 4, 1: 3})
Intersection would presumably be Counter({2: 1, 1: 1})

You can probably work out what the other standard set operations would look like.

This would be a fun class to write. It would involve more than five lines of code, but at the end of it you'd be able to create and work with MultiSet objects, and that'd be fun.
Was This Post Helpful? 0
  • +
  • -

#6 DK3250   User is offline

  • Pythonian
  • member icon

Reputation: 406
  • View blog
  • Posts: 1,312
  • Joined: 27-December 13

Re: set operations on sets with more than one of the same member

Posted 08 March 2018 - 12:04 PM

Just a small catch:
Jon's output should be:
Counter({3: 3, 4: 3, 'five': 2, 'six': 1, 2: 3, 1: 3})...the value '2' is only represented 3 times, not 4.
Was This Post Helpful? 1
  • +
  • -

#7 jon.kiparsky   User is online

  • Beginner
  • member icon


Reputation: 11069
  • View blog
  • Posts: 18,906
  • Joined: 19-March 11

Re: set operations on sets with more than one of the same member

Posted 08 March 2018 - 12:12 PM

Thanks for the correction.
Was This Post Helpful? 0
  • +
  • -

#8 bobsmith76   User is offline

  • D.I.C Head

Reputation: 9
  • View blog
  • Posts: 211
  • Joined: 14-February 17

Re: set operations on sets with more than one of the same member

Posted 08 March 2018 - 02:32 PM

Thanks everyone for their input. This is the solution that I eventually decided to go with:

    for var, lst in vars.items():
        if len(set(lst)) != len(lst):
            ct = collections.Counter(lst)
            for k, v in dict(ct).items():
                if v > 1:
                    e = 0
                    for f, prop in enumerate(lst):
                        if prop == k:
                            e += 1
                            prop = prop + str(e)
                            lst[f] = prop
    for var, lst in vars.items():
        vars[var] = set(lst)


Was This Post Helpful? 0
  • +
  • -

#9 DK3250   User is offline

  • Pythonian
  • member icon

Reputation: 406
  • View blog
  • Posts: 1,312
  • Joined: 27-December 13

Re: set operations on sets with more than one of the same member

Posted 08 March 2018 - 02:50 PM

It is extremely difficult to follow your code.
Please show a full example including 'vars'; apparently, a dictionary containing lists as items...
Was This Post Helpful? 1
  • +
  • -

#10 jon.kiparsky   User is online

  • Beginner
  • member icon


Reputation: 11069
  • View blog
  • Posts: 18,906
  • Joined: 19-March 11

Re: set operations on sets with more than one of the same member

Posted 08 March 2018 - 03:01 PM

You might also want to express this as a function. This will force you to give it a name, and that name will give me a clue as to what you intend this code to be doing for you, which would be useful.
Was This Post Helpful? 1
  • +
  • -

#11 bobsmith76   User is offline

  • D.I.C Head

Reputation: 9
  • View blog
  • Posts: 211
  • Joined: 14-February 17

Re: set operations on sets with more than one of the same member

Posted 08 March 2018 - 11:04 PM

Well it would be easier to give an example if I could pickle a typical dictionary for this code. Is there some website that allows for pickles to be opened on the website or would each user simply have to download the pickle and specify where the pickle is on their computer?
Was This Post Helpful? 0
  • +
  • -

#12 jon.kiparsky   User is online

  • Beginner
  • member icon


Reputation: 11069
  • View blog
  • Posts: 18,906
  • Joined: 19-March 11

Re: set operations on sets with more than one of the same member

Posted 08 March 2018 - 11:13 PM

Probably easier from our point of view if it's a dict that you can represent in standard dict notation. The minimal case is what we want, we'd like to be able to see the structure of the thing. If we need a more realistic example later on, we'll burn that bridge when we get to it.
Was This Post Helpful? 0
  • +
  • -

#13 bobsmith76   User is offline

  • D.I.C Head

Reputation: 9
  • View blog
  • Posts: 211
  • Joined: 14-February 17

Re: set operations on sets with more than one of the same member

Posted 08 March 2018 - 11:38 PM

Here's a simplified example. The largest dictionary will have 30 items and some values will have about 3 or 4 of the same member. Vars stands for variables and prop stands for properties.

def make_vars_different(vars):
    vars = {"e": ["Ho", "Ho", "Ss", "To"],
            "f": ["Bo", "Bo", "Bs", "Ts", "RDo", "RDp"],
            "g": ["Po", "INMo", "Po"]}
    
    for var, lst in vars.items():
        if len(set(lst)) != len(lst):
            ct = collections.Counter(lst)
            for k, v in dict(ct).items():
                if v > 1:
                    e = 0
                    for f, prop in enumerate(lst):
                        if prop == k:
                            e += 1
                            prop = prop + str(e)
                            lst[f] = prop
    for var, lst in vars.items():
        vars[var] = set(lst)

    return


Was This Post Helpful? 0
  • +
  • -

#14 DK3250   User is offline

  • Pythonian
  • member icon

Reputation: 406
  • View blog
  • Posts: 1,312
  • Joined: 27-December 13

Re: set operations on sets with more than one of the same member

Posted 09 March 2018 - 09:55 AM

Hm, I see some issues here.
1. Line 17-18 are not necessary, you have just ensured that 'lst' is populated by unique members only.
2. I suggest an extra function for increased readability, see the code below.
3. 'vars' is the name of a build-in function, I have changed it to 'varis'

My take:
import collections

def make_vars_different(varis):
    
    for lst in varis.values():  # only use .values() not .items()
        if len(set(lst)) != len(lst):
            ct = collections.Counter(lst)
            for k, v in dict(ct).items():
                if v > 1:
                    add_number(lst, k)
    return varis


def add_number(lst, k):
    number = 0
    for f, prop in enumerate(lst):
        if prop == k:
            number += 1
            prop = prop + '_' + str(number)  # an underline is added for better eye-catch
            lst[f] = prop


varis = {"e": ["Ho", "Ho", "Ss", "To"],
        "f": ["Bo", "Bo", "Bs", "Ts", "RDo", "RDp"],
        "g": ["Po", "INMo", "Po"]}

v = make_vars_different(varis)

print(v)


This post has been edited by DK3250: 09 March 2018 - 10:03 AM

Was This Post Helpful? 0
  • +
  • -

#15 bobsmith76   User is offline

  • D.I.C Head

Reputation: 9
  • View blog
  • Posts: 211
  • Joined: 14-February 17

Re: set operations on sets with more than one of the same member

Posted 09 March 2018 - 12:52 PM

cool. thanks for the input. i'm starting to like sharing my code. about the unncessary lines, i realized they were unnecessary after i posted it. and as for splitting it into two functions, yea, sometimes i get lazy and put them together.
Was This Post Helpful? 0
  • +
  • -

  • (3 Pages)
  • +
  • 1
  • 2
  • 3