Does the subject response array index match with subject's id?

Let’s say I have some code that fetches every subject from WK and puts them in an array. Can I assume that if I access, for example, array[5], the subject stored in array[5] will have the id of 5?

I believe so, but isn’t is silly to rely on that when the ID is right there?

3 Likes

Short answer: no. That is unless you populate the array with something like
subjectArray[item.id] = item to make the array index match the subject’s Id.

2 Likes

I want to rely on accessing the cached array element immediately, without having to search for the id. I think that’ll be faster, especially when I have to dig through a day worth of reviews (or not?)

Yeah, you’re right, they mismatch by a LOT. I guess that’s related to WK progressing over time
Guess I’ll have to sort them by id now :confused:
Anyway, thanks :slightly_smiling_face:

2 Likes

If you want to be able to arbitrarily fetch subjects by ID, then an array isn’t the right data structure to use. A hash table (Object in JS, dictionary in Python) is designed for looking up an item with a known identifier.

I assume OP is using Javascript. In this language arrays allow to index items by a known integer like a Python dictionary.

I am using a list of dictionaries in python (dictionary is similar to how a hash table works in python), it’s just easier to iterate through
edit: I am not really a pro in python, so maybe I am making a noob mistake, I was just using the knowledge I had

update: yes, they don’t match at all but you should be able to sort the array by ids in each element. You should keep in mind, that for some reason some ids don’t exist in WK (for example try getting subject no. 2654 or 3198). So if you decide to sort the subjects by their id in an array, you should make a cleanup function which iterates through the sorted array and adds null elements when ids are missing :smiley:

I think you mean to index the array by the id. If if were sorted by a sorting algorithm there would be no empty entries that need to be initialized as null.

Then it should be just as easy to use a dictionary of dictionaries.

for key in sub_dict:
    print(f"{key} -> {sub_dict[key]}")

Or:

for key, sub in sub_dict.items():
    print(f"{key} -> {sub}")

Dictionaries don’t have any guarantee of being arranged in any particular order, but if you want them indexed according to id, they’re the best option.

1 Like

There are no empty entries when sorted, it’s just that after you sort, the first subject missing in the WK database makes the array index and subject id not match

Maybe I’ll implement that later, thanks :wink:

This is how I understood it too but I was thrown off by this bit:

1 Like

I went back to look at some of my old code, and I found this:

import urllib
import requests

API_KEY = "CHANGE-ME"
WK_BASE_PATH = "https://api.wanikani.com/v2/"

def make_request(endpoint, *args, **kwargs):
    '''
    endpoint: the desired API resource to request:
    make_request("subjects") will call out to /subjects

    the first unnamed argument after endpoint will be added to the path:
    make_request("subjects", 1) will call out to /subjects/1

    named arguments will be added as query parameters:
    make_request("subjects", types="kanji") calls out to /subjects?types=kanji

    It will automatically follow next_url if one exists, and will only return the data portion of the response.
    '''

    path = WK_BASE_PATH + endpoint
    if len(args) > 0:
        path += f"/{args[0]}"
    path += "?" + urllib.parse.urlencode(kwargs)

    return _request_until_empty(path)


def _request_until_empty(path):
    next_path = path
    ret_data = []
    while next_path is not None:
        json = _send_request(next_path)
        data = json["data"]
        if type(data) is list:
            ret_data += data
        else:
            ret_data = data
        if "pages" in json:
            next_path = json["pages"]["next_url"]
        else:
            next_path = None
    return ret_data


def _send_request(url):
    headers = {
        "Authorization": f"Bearer {API_KEY}",
        "Wanikani-Revision": "20170710"
    }
    return requests.get(url, headers=headers).json()

A call to make_request("subject") would return a list of all subjects. If you want to be able to access them by Subject ID, then you would do something like this:

sub_dict = {}
for subject in make_request("subjects"):
    sub_dict[subject["id"]] = subject
2 Likes