2

Slicing is available for lists in python

list1 =[1,2,3,4,5,6]
list1[:3]
[1, 2, 3]

Similarly, slicing or anything similar to that available for dictionary ?

dict1 = {1":a",2:"b",3:"c",4:"d",5:"e"} 

I would like to get any 3 (can be random) elements of dictionary, just providing the number (as provided above for list [:2]), then i should be getting below dictionary

dict1 = {1":a",2:"b"} # After slicing

How can this dictionary slicing or alternative be achieved in python & Robot-framework ?

StackGuru
  • 471
  • 1
  • 9
  • 25
  • 2
    Possible duplicate of [Slicing a dictionary](https://stackoverflow.com/questions/29216889/slicing-a-dictionary) – b-fg Dec 08 '18 at 06:23
  • @b-fg How do you slice it in robot framework ? Is this duplicate ? – StackGuru Dec 08 '18 at 06:38
  • And in python, how do you limit dictionary size (slice it) by just providing the size as in list ? I don't see that in the link provided by you. – StackGuru Dec 08 '18 at 06:40
  • Keep in mind that in Python 2 and pre-3.6 the dictionaries are unordered collection, a slice would return different results on each run. – Todor Minakov Dec 09 '18 at 06:04

3 Answers3

2

Maybe this is a solution you could consider, since a dict can not be accessed as a list:

dict1 = {1:"a",2:"b",3:"c",4:"d",5:"e"}

def take(dct, high=None, low=None):
  return dict(list(dct.items())[low:high])

print(take(dict1, 3)) #=> {1: 'a', 2: 'b', 3: 'c'}
print(take(dict1, 5, 2)) #=> {3: 'c', 4: 'd', 5: 'e'}
StackGuru
  • 471
  • 1
  • 9
  • 25
iGian
  • 11,023
  • 3
  • 21
  • 36
  • Thank you very much. Indeed a simple best solution. Edited above answer as it returns "TypeError: 'dict_items' object is not subscriptable" ([low:high] need to be operated on list) – StackGuru Dec 09 '18 at 15:50
0

Just to provide 2 alternatives using only Robot Framework keywords. In essence they follow a similar approach. Get the keys from the dictionary, then slice those and either modify or recreate the dictionary in the desired format.

Unless there is a specific reason to not want to use Python for this, I think this functionality should be provided by a Python keyword and not Robot Framework.

*** Settings ***
Library    Collections

*** Variables ***
&{dict1}    1=a    2=b    3=c    4=d    5=e
&{dict2}    1=a    2=b    3=c    4=d    5=e
&{result}   3=c    4=d    5=e 

*** Test Cases ***
TC - keep items 3, 4 & 5
    # Keey
    Keep Slice In Dictionary    ${dict1}    ${5}    ${2}
    Log Many    ${dict1}
    Dictionaries Should Be Equal    ${dict1}    ${result}    

    ${slice}       Get Slice From Dictionary    ${dict2}    ${5}    ${2}
    Log Many    ${slice}
    Dictionaries Should Be Equal    ${dict1}    ${slice}

*** Keywords ***
Keep Slice In Dictionary
    [Documentation]
    ...    Modifies the dictionary to only leave the slice.
    ...    
    ...    The keys of the dictionary are converted into a list. Then
    ...    this list is spliced. This list is then used to filter out
    ...    the unwanted keys.
    ...    
    ...    Note: this keyword modifies the provided dictionary.
    ...    
    ...    Arguments:
    ...    - dict    (dictionary)    The dictionary that needs to be modified
    ...    - high    (integer)       The last item to be kept.
    ...    - low     (integer)       The first item of the slice. (defaults to 0)
    ...    
    ...    Returns:    None          Modifies the provided dictionary.
    ...    
    [Arguments]    ${dict}    ${high}    ${low}=${0}

    ${keys_list}        Get Dictionary Keys    ${dict}
    ${filtered_keys}    Get Slice From List    ${keys_list}    ${low}    ${high}
    Keep In Dictionary     ${dict}    @{filtered_keys}

Get Slice From Dictionary
    [Documentation]
    ...    Get a slice of sequential keys from a dictionary
    ...    
    ...    The keys of the dictionary are converted into a list. Then
    ...    this list is spliced. This list is then used to create a new
    ...    Dictionary with the filtered keys.
    ...    
    ...    Arguments:
    ...    - dict    (dictionary)    The source dictionary
    ...    - high    (integer)       The last item to be kept.
    ...    - low     (integer)       The first item of the slice. (defaults to 0)
    ...    
    ...    Returns:  (dictionary     A dictionary with the desired keys.
    ...    
    [Arguments]    ${dict}    ${high}    ${low}=${0}
    ${keys_list}        Get Dictionary Keys    ${dict}
    ${filtered_keys}    Get Slice From List    ${keys_list}    ${low}    ${high}

    ${return_dict}    Create Dictionary

    :FOR    ${item}    IN    @{filtered_keys}
    \        Set To Dictionary    ${return_dict}   ${item}    ${dict['${item}']}

    [Return]     ${return_dict}
A. Kootstra
  • 6,827
  • 3
  • 20
  • 43
0

I would like to get any 3 (can be random) elements of dictionary

Constructing a list of all dictionary items is not necessary. You can use the dict.items and itertools.islice to slice a fixed number of items:

from itertools import islice

def get_n_items(d, n):
    return dict(islice(d.items(), 0, n))

dict1 = {1:"a", 2:"b", 3:"c", 4:"d", 5:"e"} 

get_n_items(dict1, 2)  # {1: 'a', 2: 'b'}
get_n_items(dict1, 3)  # {1: 'a', 2: 'b', 3: 'c'}

With Python 3.6+, as an implementation detail in CPython 3.6 and officially in 3.7+, this equates to taking the first n items by inseration order.

jpp
  • 159,742
  • 34
  • 281
  • 339