Search code examples
python-3.xnamedtuplepython-dataclasses

How to get key and values using NamedTuple


Python 3.9.6

I have been trying to figure out on how I am able to print the key and value when I have given variable that I want to specific get from a NamedTuple.

I have created my own NamedTuple that I import via configuration that reads TOML file which can be read below:

from config import configuration

"""
[discord]
    [discord.filtered]
        [[discord.filtered.swedish]]
            eu = "https://discordapp.com/api/webhooks/1...."
            asia = "https://discordapp.com/api/webhooks/2...."
            
        [[discord.unfiltered.mixed]]
            eu = "https://discordapp.com/api/webhooks/7...."
            asia = "https://discordapp.com/api/webhooks/8..."   
            
    [discord.unfiltered]
        [[discord.unfiltered.swedish]]
            eu = "https://discordapp.com/api/webhooks/3...."
            asia = "https://discordapp.com/api/webhooks/4...."
         
        [[discord.unfiltered.mixed]]
            eu = "https://discordapp.com/api/webhooks/5...."
            asia = "https://discordapp.com/api/webhooks/6..."   
"""
filtered = True  # Or False
type_filter = "swedish"  # Or mixed

collection = configuration.discord.filtered if filtered else configuration.discord.unfiltered

I was able to figure out if filtered is true then we go into the filtered path in the configuration else unfiltered, but then my problem starts here. I do not know how I can print out the region and the URL if I want to use swedish or mixed.

The output I want to get is that e.g.

filtered = True  # Or False
type_filter = "swedish"  # Or mixed

should print out

eu,  https://discordapp.com/api/webhooks/1....
asia, https://discordapp.com/api/webhooks/2....

where eu/asia is one variable and the URL its own variable

How am I able to print the region and the url based on filtered and type_filter?

Update after Enzo answer:

filtered = True  # Or False
type_filter = "swedish"  # Or mixed

collection = configuration.discord.filtered if filtered else configuration.discord.unfiltered

for regions in getattr(collection, type_filter):
    for region, discord_collection in regions.items():
        print(f"Region: {region}, URL {discord_collection}")

Solution

  • You can use the toml library:

    data = """
    [discord]
        [discord.filtered]
            [[discord.filtered.swedish]]
                eu = "https://discordapp.com/api/webhooks/1...."
                asia = "https://discordapp.com/api/webhooks/2...."
                
            [[discord.unfiltered.mixed]]
                eu = "https://discordapp.com/api/webhooks/7...."
                asia = "https://discordapp.com/api/webhooks/8..."   
                
        [discord.unfiltered]
            [[discord.unfiltered.swedish]]
                eu = "https://discordapp.com/api/webhooks/3...."
                asia = "https://discordapp.com/api/webhooks/4...."
             
            [[discord.unfiltered.mixed]]
                eu = "https://discordapp.com/api/webhooks/5...."
                asia = "https://discordapp.com/api/webhooks/6..."   
    """
    
    import toml
    
    mapping = toml.loads(data)
    print(mapping)
    

    Outputs

    {'discord': {'discord.filtered': {'discord.filtered.swedish': {'asia': '...', 'eu': '...'},
                                      'discord.unfiltered.mixed': {'asia': '...', 'eu': '...'}},
                 'discord.unfiltered': {'discord.unfiltered.mixed': {'asia': '...', 'eu': '...'},
                                        'discord.unfiltered.swedish': {'asia': '...', 'eu': '...'}}}}
    

    Then, just create a function to filter the resulting dictionary:

    def filter_dict(dicts, name: str, filtered: bool):
        key_1st = "discord"
        key_2nd = "filtered" if filtered else "unfiltered"
        key_3rd = name
        return dicts[key_1st]['.'.join((key_1st, key_2nd))]['.'.join((key_1st, key_2nd, key_3rd))] 
    
    print(filter_dict(mapping, name="swedish", filtered=True))
    # Outputs {'eu': 'https://discordapp.com/api/webhooks/1....', 'asia': 'https://discordapp.com/api/webhooks/2....'}