PythonNewbie
PythonNewbie

Reputation: 1163

How to add values to several Sets

I have currently trying to extract from database to be able to put values to various sets. e.g.

So I have created something like this:

from typing import Tuple, Set

MOCK_DATABASE = [
    {"python": True},
    {"no": True},
    {"hello world": True},
    {"java": False},
    {"ruby js": False},
    {"c#": False}
]

SINGLE_POSITIVE: Set[str] = {}
MULTI_POSITIVE: Tuple[Set[str], ...] = ()
SINGLE_NEGATIVE: Set[str] = {}
MULTI_NEGATIVE: Tuple[Set[str], ...] = ()

for database_value in MOCK_DATABASE:
    for att, value in database_value.items():
        if value and ' ' in att:
            MULTI_POSITIVE.add(att)
        elif value:
            SINGLE_POSITIVE.add(att)
        elif not value and ' ' in att:
            MULTI_NEGATIVE.add(att)
        else:
            SINGLE_NEGATIVE.add(att)

print(f"Single positive: {SINGLE_POSITIVE}")
print(f"Multi positive: {MULTI_POSITIVE}")
print(f"Single negative: {SINGLE_NEGATIVE}")
print(f"Multi negative: {MULTI_NEGATIVE}")

Wanted output:

SINGLE_POSITIVE: Set[str] = {
    "python",
    "no",
}
MULTI_POSITIVE: Tuple[Set[str], ...] = (
    {"hello", "world"},
)

SINGLE_NEGATIVE: Set[str] = {
    "java",
    "c#",
}
MULTI_NEGATIVE: Tuple[Set[str], ...] = (
    {"ruby", "js"},
)

However when I execute the script, I get an error saying:

SINGLE_POSITIVE.add(att)
AttributeError: 'dict' object has no attribute 'add'

My question is, how can I set it so I have the wanted output?

EDIT:

Thanks for the small fix from the answers below:

I have now changed to SINGLE_POSITIVE: Set[str] = set()

but that returns now

    MULTI_POSITIVE.add(att)
AttributeError: 'tuple' object has no attribute 'add'

Upvotes: 0

Views: 45

Answers (2)

AWSM
AWSM

Reputation: 78

There's a few issues in the code:

  1. Per codebreach's answer, you have to initialize the set using set().
  2. You can't add elements to tuples; they're immutable. Your best bet is to initialize the MULTI variables as lists, then convert them at the end.
  3. You need to split the keys to get them as multiple separated elements in the set.
from typing import List, Tuple, Set

MOCK_DATABASE = [
    {"python": True},
    {"no": True},
    {"hello world": True},
    {"java": False},
    {"ruby js": False},
    {"c#": False},
]

SINGLE_POSITIVE: Set[str] = set()
MULTI_POSITIVE: List[Set[str]] = []
SINGLE_NEGATIVE: Set[str] = set()
MULTI_NEGATIVE: List[Set[str]] = []

for database_value in MOCK_DATABASE:
    for att, value in database_value.items():
        if value and " " in att:
            MULTI_POSITIVE.append(set(att.split()))
        elif value:
            SINGLE_POSITIVE.add(att)
        elif not value and " " in att:
            MULTI_NEGATIVE.append(set(att.split()))
        else:
            SINGLE_NEGATIVE.add(att)

MULTI_POSITIVE_TUP = tuple(MULTI_POSITIVE)
MULTI_NEGATIVE_TUP = tuple(MULTI_NEGATIVE)

print(f"Single positive: {SINGLE_POSITIVE}")
print(f"Multi positive: {MULTI_POSITIVE_TUP}")
print(f"Single negative: {SINGLE_NEGATIVE}")
print(f"Multi negative: {MULTI_NEGATIVE_TUP}")

Gives:

Single positive: {'python', 'no'}
Multi positive: ({'hello', 'world'},)
Single negative: {'c#', 'java'}
Multi negative: ({'js', 'ruby'},)

Just another point, on reflection, there's another issue that's more design-wise than programmatical. There's no reason for your MOCK_DATABASE to be a list of dictionaries, rather than a single dictionary. A dictionary can have several key: value pairs and I can't think of a single example (off the top of my head) where it's useful to define a dictionary with one entry. If this MOCK_DATABASE is more complex than the one in your example, you might consider using the pandas library.

Upvotes: 1

codebreach
codebreach

Reputation: 2220

The problem is that you have type hints that say SINGLE_POSITIVE and SINGLE_NEGATIVE are Sets but your code is initializing them to a dict

SINGLE_POSITIVE: Set[str] = {}

# should become 

SINGLE_POSITIVE: Set[str] = set()

Upvotes: 1

Related Questions