-1

I would like to extract the second key of every dictionary using a for loop. However, the dictionaries are nested in a list (see below). Also, notice that the second key is not always the same.

video_Ids = [
{'kind': 'youtube#playlist',
  'playlistId': 'PLt1O6njsCRR-D_1jUAhJrrDZyYL6OZSGa'},
 {'kind': 'youtube#playlist',
  'playlistId': 'PLt1O6njsCRR_8oi7E6qnPWGQbn8NoQ6sG'},
 {'kind': 'youtube#channel', 'channelId': 'UC4i5R6-IW05iiU8Vu__vppA'},
 {'kind': 'youtube#video', 'videoId': 'XquM0L2WUio'},
 {'kind': 'youtube#video', 'videoId': '05yrGVZ96b4'}
]

I have tried different things but none have worked so far. Here is my last attempt: deleting the first key to be left with a list containing the second keys.

for i in video_Ids:
    if video_Ids["kind"] == "youtube#video":
        del video_Ids[i]["kind"]
    elif video_Ids[i]["kind"] == "youtube#playlist":
        del video_Ids[i]["kind"]
    elif video_Ids[i]["kind"] == "youtube#channel":
        del video_Ids[i]["kind"]

this is the message I get:

TypeError: list indices must be integers or slices, not str

I tried my best and got stuck on this for a few days now. I really appreciate any help, Thank you.

rboemer
  • 15
  • 4
  • In the code you provided `i` is a dictionary and not number (not an index), to fix that you can do `range(len(video_Ids))`. – Julio Suriano Jan 07 '21 at 14:24

4 Answers4

1

You don't need to use the index once you have the dictionary:

for video in video_Ids:
    if video["kind"] == "youtube#video":
        del video["kind"]
    elif video["kind"] == "youtube#playlist":
        del video["kind"]
    elif video["kind"] == "youtube#channel":
        del video["kind"]

To extract the second key, you need to iterate on each dictionary. For example:

from itertools import islice
secondKeys = [ {k:v} for d in video_Ids for k,v in islice(d.items(),1,2)]

# or without itertools ...

secondKeys = [ {k:v} for d in video_Ids for _,(k,v),*_ in [d.items()]]
    
print(secondKeys)
[{'playlistId': 'PLt1O6njsCRR-D_1jUAhJrrDZyYL6OZSGa'},
 {'playlistId': 'PLt1O6njsCRR_8oi7E6qnPWGQbn8NoQ6sG'},
 {'channelId': 'UC4i5R6-IW05iiU8Vu__vppA'},
 {'videoId': 'XquM0L2WUio'},
 {'videoId': '05yrGVZ96b4'}]

or, if you only want the keys and not the corresponding values:

from itertools import islice
secondKeys = [ k for d in video_Ids for k in islice(d,1,2)]

# or without itertools ...

secondKeys = [ k for d in video_Ids for _,k,*_ in [d]]

print(secondKeys)
['playlistId', 'playlistId', 'channelId', 'videoId', 'videoId']
Alain T.
  • 40,517
  • 4
  • 31
  • 51
0

There are two ways to fix your code:

Version1

video_Ids = [
{'kind': 'youtube#playlist',
  'playlistId': 'PLt1O6njsCRR-D_1jUAhJrrDZyYL6OZSGa'},
 {'kind': 'youtube#playlist',
  'playlistId': 'PLt1O6njsCRR_8oi7E6qnPWGQbn8NoQ6sG'},
 {'kind': 'youtube#channel', 'channelId': 'UC4i5R6-IW05iiU8Vu__vppA'},
 {'kind': 'youtube#video', 'videoId': 'XquM0L2WUio'},
 {'kind': 'youtube#video', 'videoId': '05yrGVZ96b4'}
]



for id in video_Ids:
    if id["kind"] == "youtube#video":
        del id["kind"]
    elif id["kind"] == "youtube#playlist":
        del id["kind"]
    elif id["kind"] == "youtube#channel":
        del id["kind"]

Version2

video_Ids = [
{'kind': 'youtube#playlist',
  'playlistId': 'PLt1O6njsCRR-D_1jUAhJrrDZyYL6OZSGa'},
 {'kind': 'youtube#playlist',
  'playlistId': 'PLt1O6njsCRR_8oi7E6qnPWGQbn8NoQ6sG'},
 {'kind': 'youtube#channel', 'channelId': 'UC4i5R6-IW05iiU8Vu__vppA'},
 {'kind': 'youtube#video', 'videoId': 'XquM0L2WUio'},
 {'kind': 'youtube#video', 'videoId': '05yrGVZ96b4'}
]



for i in range(len(video_Ids)): #iterate over a range instead 
    if video_Ids[i]["kind"] == "youtube#video":
        del video_Ids[i]["kind"]
    elif video_Ids[i]["kind"] == "youtube#playlist":
        del video_Ids[i]["kind"]
    elif video_Ids[i]["kind"] == "youtube#channel":
        del video_Ids[i]["kind"]

As you can see from these examples, you can either iterate through an array created from the length of the list and provide the index, or just directly iterate through the list, but then id is not an index, but the current dictionary.

Roland Deschain
  • 2,211
  • 19
  • 50
0

Try this:

video_Ids = [
{'kind': 'youtube#playlist',
'playlistId': 'PLt1O6njsCRR-D_1jUAhJrrDZyYL6OZSGa'},
{'kind': 'youtube#playlist',
'playlistId': 'PLt1O6njsCRR_8oi7E6qnPWGQbn8NoQ6sG'},
{'kind': 'youtube#channel', 'channelId': 'UC4i5R6-IW05iiU8Vu__vppA'},
{'kind': 'youtube#video', 'videoId': 'XquM0L2WUio'},
{'kind': 'youtube#video', 'videoId': '05yrGVZ96b4'}
]

list_of_keys = []

for _, second_key in video_Ids:
    list_of_keys.append(second_key)

Prints:

['playlistId', 'playlistId', 'channelId', 'videoId', 'videoId']

and if you want also the value just write this:

list_of_keys = []

for index, _ in enumerate(video_Ids):
    list_of_keys.append(list(video_Ids[index].items())[1])

Prints:

[('playlistId', 'PLt1O6njsCRR-D_1jUAhJrrDZyYL6OZSGa'), ('playlistId', 'PLt1O6njsCRR_8oi7E6qnPWGQbn8NoQ6sG'), ('channelId', 'UC4i5R6- IW05iiU8Vu__vppA'), ('videoId', 'XquM0L2WUio'), ('videoId', '05yrGVZ96b4')]
Higs
  • 384
  • 2
  • 7
0

As others have pointed out, it looks like you also have a bug in your if statements. Since the elements of video_Ids are dictionaries, i will be a dictionary, so your if statement should reference i["kind"] rather than video_Ids[i]["kind"].

More importantly, though, you should never rely on dictionary keys being in a specific order. Since python 3.7, keys will be preserved in the order in which they were inserted, but that doesn't mean they're sorted alphabetically or anything. That's not the point of a dictionary. See the docs on data types and the answers to this question on dictionary key ordering for more background.

If you know the dictionaries will have two keys, one of which is "kind", you could always iterate over the keys to find the key name that isn't "kind", e.g.:

# optional test to check for 2 keys
assert len(i) == 2, f"Number of keys does not equal 2: {i.keys()}"

# filter the keys for the one that isn't "kind" and extract the result
other_key=[k for k in i.keys() if k != 'kind'][0]

If you put this inside your for-loop you should have the name of the other key, which you can use to refer to the unknown element as i[other_key].

The other option is to construct the keys using the structure internal to your data. It seems that kind can actually be used to construct the other key - this seems to be the intended layout of your data. So another option for retrieving the IDs in your data is to construct the key in each loop element:

# use last part of kind, starting from end of "youtube#" substring
media_type = i["kind"][len("youtube#"):]

media_id_key = media_type + "ID"
media_id = i[media_id_key]
Michael Delgado
  • 13,789
  • 3
  • 29
  • 54