1

I have a total number of tasks at 6716, and a dictionary consisting of a token as key and a length as item. What i need to do is to count up to the first length in the dictionary. In other words, if I have a total task of 6716 and dictionary = {'tok1':5121}, then I need to do something when iterating up to 5121. If the dictionary looks like: dictionary = {'tok1':5121, 'tok2':802, 'tok3':793}, then it would need to do something when iterating the first 5121, then it should do something else the next 802, and eventually do something else when iterating the next 793, which would all sum up to iterating to 6716.

I imagined that it would look something like the following:

num_tasks = 6716
dict = {'tok1':5121, 'tok2':802, 'tok3':793}

for i in range(num_tasks):
   if i <= dict['tok1']
       do something...
   elif i > dict['tok1'] and i <= dict['tok1'] + dict['tok2']
       do something...
   elif i > dict['tok1'] + dict['tok2']
       do something...

Although this in theory should work, it is not the most optimal way of looping, since we might have 1000's of tokens one day, and therefore I would need to add 1000's if statements, which isn't very scalable. Therefore, I need help to find a more dynamic way of looping like this.

CODE

    list = ['tok1', 'tok2', 'tok3']
    dict = {'tok1':5121, 'tok2':802, 'tok3':793}
    nexts = iter(customerNumbers)
    try:
        for i in range(n_tasks): # n_tasks = 6716

            single = file['xxx'][i]
            test = file['xxx'][i]['number']

            if test in custom:
                self.params["skippages"] += 1

            if test in customerNumbers: # customerNumbers is a list containing numbers of customers
                url = self.url + f'customers/{next(nexts)}' 
                 
                # Here i need to say that for the first 5121 in num_tasks, change token to the first item in the list containing tokens, then for the next 802 in num_tasks change token to 'tok2' from the list containing tokens etc.
                # For example: if i <= 5121 then token = list[0], if i > 5121 and i < 5121+802 then change token = list[1] etc.
                headers = {'X-AppSecretToken': self.secret_token, 'X-AgreementGrantToken': {token}, 'Content-Type': "application/json"}
                pool.apply_async(request_put, args=(url, headers, self.params, json.dumps(single)))

    except StopIteration:
        pass

    # wait for all tasks to complete:
    pool.close()
    pool.join()

def request_put(url, headers, params, single):
    return requests.put(url=url, headers=headers, params=params, data=single)
7
  • A dictionary has no order, so it is odd you want to follow a certain order. Perhaps you need to consider a different container? Commented Jul 14, 2021 at 11:09
  • I assume the order is specified by the tok_i i.e tok1>tok2.. Commented Jul 14, 2021 at 11:10
  • What order are the keys in? Is it the order in which they were created or perhaps some lexicographical order? Commented Jul 14, 2021 at 11:10
  • @ThePyGuy It does, but I don't think one shouldn't rely on this. Make it clear, use an ordered dictionary or similar. Commented Jul 14, 2021 at 11:10
  • 1
    Also, what is the nature of the do something...? Perhaps you will need 1000 if statements to get the right things done in each case. Commented Jul 14, 2021 at 11:11

5 Answers 5

2

In case your "do something" are similar-ish across tokens, then a possibility is the following:

for k, v in dic.items():
    for i in range(v):
        # "do something"
        # where k is the token and v is the length
Sign up to request clarification or add additional context in comments.

5 Comments

I think the issue is, when i is between intervals i.e between 5121 and 5121+802
@CutePoison: The line: for i in range(v): obviates any calculations like: 5121+802 etc.
but it would then run from 0-v, wouldnt it?
@CutePoison: Yes, exactly. The inner loop runs from 0-5120, then 0-801 etc.
Yes, with this code the counter goes back to zero for each token. Whether this is okay is up to OP's "do something"
0

you still have the problem of multiple if's if you are going to do something different to each range,

but this will automatically give you each range:

dictt = {'tok1':5121, 'tok2':802, 'tok3':793}

lisdict = list(dictt)
start = 0
end = 0
for i in range(len(lisdict)):
    if i != 0:
        # if =
        start = dictt[lisdict[i-1]] + start
        end = dictt[lisdict[i]] + start
        print (f"from: {start}")
        print (f"to: {end}")
        # if i == 1:
        #     "do something"
        # if i == 2:
        #     "do something"
        # .
        # .
        # .

2 Comments

where if i==1 will basicaly mean from tok1 to tok2
if you need to do different condition for some ranges, and same conditions for other ranges you can say, if i==1 or i == 3, do something. which will mean for tok1-2 and tok3-4 do the same thing
0

I would advice to create your intervals as a list, write a function for each "interval" and then chose the function, based on what interval your i is in.

First, create intervals

import numpy as np
d = {'tok1':5121, 'tok2':802, 'tok3':793} #Dont use "dict" as variable
interval = list(d.values()) # [5121,802,793]

interval_higher = np.cumsum(interval) # array([5121, 5923, 6716], dtype=int32)
interval_lower = [0]
interval_lower.extend(interval_higher[:-1]) 
interval_lower = np.array(interval_lower) # np.array([0, 5121, 5923])

now we define a list of functions for each interval


def func1():
    pass
def func2():
    pass
def func3():
    pass

func_list = [func1,  #Define your functions for each interval
    func2,
    func3,
]
func_list = np.array(func_list)

atlast, loop, get the index of where your i is in, and get the apropiate function

for i in range(tasks):
    idx_high = i<=interval_higher
    idx_low = i>interval_lower

    func_idx = idx_high & idx_low #Get the index of function e.g [False,True,False] --> second interval (tok2)

    func = func_list[func_idx] #Get the function for tok2
    func() #Run it

The full script

import numpy as np
d = {'tok1':5121, 'tok2':802, 'tok3':793} #Dont use "dict" as variable
interval = list(d.values()) # [5121,802,793]

interval_higher = np.cumsum(interval) # array([5121, 5923, 6716], dtype=int32)
interval_lower = [0]
interval_lower.extend(interval_higher[:-1]) # [0, 5121, 5923]
interval_lower = np.array(interval_lower)


func_list = [func1,  #Define your functions for each interval
    func2,
    func3,
]
func_list = np.array(func_list)

tasks = 6716
for i in range(tasks):
    idx_high = i<=interval_higher
    idx_low = i>interval_lower

    func_idx = idx_high & idx_low #Get the index of function e.g [False,True,False] --> second interval (tok2)

    func = func_list[func_idx] #Get the function for tok2
    func() #Run the function

Comments

0

This assumes keys ids are sequential. You could change the current token based on each token's range.

dict = {'tok1':(5121, 'token-01'), 'tok2':(802, 'token-02')}

current_id = 1
current_token = dict[f'tok{current_id}'][1]
done_tasks = 0

for i in range(tasks):
   if i >= dict[f'tok{current_id}'] + done_tasks:
       done_tasks += dict[f'tok{current_id}'][0]
       current_id += 1
       current_token = dict[f'tok{current_id}'][1] 
   do_something_with_current_token(current_token)

Comments

0

Assuming you have to work with the numbers of the tasks and assigning them one of the tokens based on the interval they are in, this could be an implementation:

tasks = 10
d = {'tok1':3, 'tok2':5, 'tok3':1, 'tok4':1}

keys = list(d.keys())

counter = 0

for i in range(len(d)):

    if i == 0:
        for j in range(counter, d[keys[i]]):
            print('task {} using {}'.format(counter, keys[i])) # or do something ...
            counter += 1

    elif i == (len(d)-1):
        for j in range(counter, counter+d[keys[i]]):
            print('task {} using {}'.format(counter, keys[i])) # or do something ...
            counter += 1
        
    else:
        for j in range(counter, counter+d[keys[i]]):
            print('task {} using {}'.format(counter, keys[i])) # or do something ...
            counter += 1

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.