How to extract data from a list of dictionaries from a filter

Viewed 289

I have a list of dictionaries which is a scrape of HTML elements from a forum:

[{'title': 'aaa', 'responses': '1 response', 'url': 'https://www.example.com/aaa'}, {'title': 'bbb', 'responses': '4 responses', 'url': 'https://www.example.com/bbb'}, {'title': 'ccc', 'responses': '2 responses', 'url': 'https://www.example.com/ccc'}, {'title': 'ddd', 'responses': '8 responses', 'url': 'https://www.example.com/ccc'}, {'title': 'eee', 'responses': '2 responses', 'url': 'https://www.example.com/eee'}]

I want to extract the 'url' items from the dictionaries if the 'reponses' item is smaller than 2 responses. I try this code which works well but only for the first item:

dict = {'url1': ''}
item1 = "1 response"
item2 = "2 responses"
if item1 in scrape[0]['responses'] or item2 in scrape[0]['responses']:
    dict['url1'] = scrape[0]['url']
    print(dict)

{'url1': 'https://www.example.com/aaa'}

If I delete the [0] element I get this: TypeError: list indices must be integers or slices, not str

I want this result:

{'url1': 'https://www.example.com/aaa', 'url2': 'https://www.example.com/eee'}

How to do this?

3 Answers

Loop over the list, and convert each value of the "responses" key into an int, then check if it is smaller than 2 and if so, print the URL (inserted an extra item, fffin l for clarity):

l = [{'title': 'aaa',
      'responses': '1 response',
      'url': 'https://www.example.com/aaa'
      },
     {'title': 'bbb', 'responses': '4 responses', 'url': 'https://www.example.com/bbb'},
     {'title': 'ccc', 'responses': '2 responses', 'url': 'https://www.example.com/ccc'},
     {'title': 'ddd', 'responses': '8 responses', 'url': 'https://www.example.com/ccc'},
     {'title': 'eee', 'responses': '2 responses', 'url': 'https://www.example.com/eee'},
     {'title': 'fff', 'responses': '1 responses', 'url': 'https://www.example.com/fff'}
 ]


def less_responses_than_n(r, n=2, count=0):
    for d in l:
        if int(d["responses"].split()[0]) < n:
            count += 1
            r[f'url_{count}'] = d["url"]
    return r


r = dict()
print(less_responses_than_n(r))
print(less_responses_than_n(r, n=3))

Returning:

{'url_1': 'https://www.example.com/aaa', 'url_2': 'https://www.example.com/fff'}
{'url_1': 'https://www.example.com/aaa', 'url_2': 'https://www.example.com/ccc', 'url_3': 'https://www.example.com/eee', 'url_4': 'https://www.example.com/fff'}

This is one approach using a simple iteration and str.split

Ex:

data = [{'title': 'aaa', 'responses': '1 response', 'url': 'https://www.example.com/aaa'}, {'title': 'bbb', 'responses': '4 responses', 'url': 'https://www.example.com/bbb'}, {'title': 'ccc', 'responses': '2 responses', 'url': 'https://www.example.com/ccc'}, {'title': 'ddd', 'responses': '8 responses', 'url': 'https://www.example.com/ccc'}, {'title': 'eee', 'responses': '2 responses', 'url': 'https://www.example.com/eee'}]
res = [item['url'] for item in data if int(item['responses'].split()[0]) < 2]
print(res)  # --> ['https://www.example.com/aaa']

You can write a function and use filter(...) on the list:

lst = [{'title': 'aaa', 'responses': '1 response', 'url': 'https://www.example.com/aaa'}, {'title': 'bbb', 'responses': '4 responses', 'url': 'https://www.example.com/bbb'}, {'title': 'ccc', 'responses': '2 responses', 'url': 'https://www.example.com/ccc'}, {'title': 'ddd', 'responses': '8 responses', 'url': 'https://www.example.com/ccc'}, {'title': 'eee', 'responses': '2 responses', 'url': 'https://www.example.com/eee'}]

def few_responses(item):
    number, _ = item['responses'].split()
    if (int(number) < 2):
        return True
    else:
        return False


for item in filter(few_responses, lst):
    print(item["url"])

Alternatively you can use a list comprehension that does the same:

urls = [item["url"]
        for item in lst
        for number, _ in [item["responses"].split()]
        if (int(number) < 2)]
print(urls)
Related