4

I am trying to loop through a list used to create dictionary keys and assign a value based upon a few different categories

For example:

list = ['cat1', 'cat2', 'cat3', 'number1', 'number2', 'number3']

my_dict = {}

for i in range(len(list)):
     if any("cat" in s for s in list):
          my_dict[list[i]] = 'categorical'
     if any("num" in s for s in list):
          my_dict[list[i]] = 'numerical'  

I am trying to get a dictionary that would loop and result in:

my_dict = {'cat1': 'categorical', 'cat2': 'categorical', 'cat3': 'categorical', 'number1': 'numerical', 'number2': 'numerical', 'number3': 'numerical'}

Thanks for any help!

1
  • 3
    Dont' name lists list, it overrides a builtin name. Commented Jun 6, 2018 at 3:02

8 Answers 8

2

If you can assume that values in your list will match one of your lookups, you can do that like:

items = ['cat1', 'cat2', 'cat3', 'number1', 'number2', 'number3']
matches = {'num': 'numerical', 'cat': 'categorical'}
result = {i: [v for k, v in matches.items() if k in i][0] for i in items}
print(result)

How?

This uses a dict to map the desired search string to a matched values. It then uses a loop comprehension to search each value in the dict and returns the matched value. The value is used as the value in the dict comprehension.

Results:

{'cat1': 'categorical', 'cat2': 'categorical', 'cat3': 'categorical',
 'number1': 'numerical', 'number2': 'numerical', 'number3': 'numerical'
}
Sign up to request clarification or add additional context in comments.

Comments

2

Stephen Rauch has a nice idea. Here's a slightly more concise version of what he's written using dict.get.

matches = {'num': 'numerical', 'cat': 'categorical'}
result = {k : matches.get(k[:3], 'unknown') for k in items}

print(result)
{'cat1': 'categorical',
 'cat2': 'categorical',
 'cat3': 'categorical',
 'number1': 'numerical',
 'number2': 'numerical',
 'number3': 'numerical'}

If you want to drop values that do not match, make a slight modification:

result = {k : matches[k[:3]] for k in items if k[:3] in matches}

Here's my take on it. Sort items first, and then find the index of discontinuity.

items.sort()

for i, l in enumerate(items):
    if l.startswith('num'):
        break

result = dict.fromkeys(items[:i], 'categorical')
result.update(dict.fromkeys(items[i:], 'numerical'))

This works best for two classes of values only.

print(result)
{'cat1': 'categorical',
 'cat2': 'categorical',
 'cat3': 'categorical',
 'number1': 'numerical',
 'number2': 'numerical',
 'number3': 'numerical'}

3 Comments

@StephenRauch No it won't, certainly not as flexible as option 1!
I like the get() here.
@StephenRauch yup, I like your answer too. Very flexible.
0

Change your code a little bit; use startswith to look for a match:

lst = ['cat1', 'cat2', 'cat3', 'number1', 'number2', 'number3']

my_dict = {}

for x in lst:
    if x.startswith('cat'):
        my_dict[x] = 'categorical'
    elif x.startswith('num'):
        my_dict[x] = 'numerical'

print(my_dict)

# {'cat1': 'categorical', 'cat2': 'categorical', 'cat3': 'categorical', 'number1': 'numerical', 'number2': 'numerical', 'number3': 'numerical'}

Comments

0
list_ = ['cat1', 'cat2', 'cat3', 'number1', 'number2', 'number3']
# Don't name the variable "list" as it is a keyword if you can't think of anything else append a underscore at end

my_dict = {}

for item in list_:
    if "cat" in item:
        my_dict[item] = 'categorical'
    elif "number" in item:
        my_dict[item] = 'numerical'

print(my_dict)

Comments

0

Your example is fairly close but has a few issues. Here is a solution that modifies your code as little as possible:

lst = ['cat1', 'cat2', 'cat3', 'number1', 'number2', 'number3']

my_dict = {}

for value in lst:
     if "cat" in value:
          my_dict[value] = 'categorical'
     if "num" in value:
          my_dict[value] = 'numerical'  

The first major issue is that you should never override a built-in. Use lst or list_ not list.

Now let's look at this bit of your code:

if any("cat" in s for s in lst):

...as you have it, this checks if "cat" appears anywhere in the list (not just in the item you meant to check).

Since this is true, 'cat1' would be assigned to categorical. But because you have another if statement that also evals to true for numerical, this result is overwritten and you end up with all of the entries being listed as numerical.

2 Comments

Why the enumerate ?
I removed it, the original code used indexes so I thought of that. Good catch, thanks
0

Try using the dictionary setdefault function:

l = ['cat1', 'cat2', 'cat3', 'number1', 'number2', 'number3']
my_dict = {}
for i in l:
    my_dict.setdefault(i,['numerical' if 'number' in i else 'category'][-1])  
print(my_dict)

Output:

{'cat1': 'category', 'cat2': 'category', 'cat3': 'category', 'number1': 'numerical', 'number2': 'numerical', 'number3': 'numerical'}

Comments

0

The simplest answer:

l = ['cat1', 'cat2', 'cat3', 'number1', 'number2', 'number3', 'junk']
d = {k: 'categorical' if 'cat' in k else 'numerical' if 'number' in k else 'unknown' for k in l}

Output:

{'cat1': 'categorical', 'cat2': 'categorical', 'cat3': 'categorical', 'number1': 'numerical', 'number2': 'numerical', 'number3': 'numerical', 'junk': 'unknown'}

Comments

0
import itertools
lst = [‘cat1’, ‘cat2’, ‘cat3’, ‘number1’, ‘number2’, ‘number3’]
values = [‘categorical’, ‘numerical’]

dict(filter(lambda item: item[0][:3] == item[1][:3], list(itertools.product(lst, values))))

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.