Is there any robot framework keyword to sort a list of strings which has special characters?

I have a list of strings which contains special characters in it, The list is below:

1.Kevin_richard
2.Dan_ronald
3.Daniel_white
4.David_jacob
5.eddie_bacon

To sort the list in ascending order I have used Sort List(The strings are sorted alphabetically and the numbers numerically) keyword from collections library.

*** Settings ***

*** Test Cases ***
TC Title
  Sort the given list of usernames in ascending order

*** Keywords ***
Sort the given list of usernames in ascending order
  ${sorted_order_asc}=  Copy List  ${default_order_username}    //default order represents list of five user names
  Sort List  ${sorted_order_asc}

On executing the above script, the list is sorted in the following order:

  1. Daniel_white
  2. Dan_ronald
  3. David_jacob
  4. eddie_bacon
  5. Kevin_richard

But this is not the expected sort order. In the above list, Dan_ronald has to be at the top of the list. Sort List ignores special characters hence underscore after Dan is skipped and checks for the next alphabet(r vs i). As a result of it, Daniel_white tops the list.

Any help to sort out this issue will be appreciated.

2 answers

  • answered 2018-11-08 08:00 A. Kootstra

    This can be most easily achieved by using a python function in the below example a custom robot keyword is created that takes a string with the correct character sort order. This then uses that to sort the list items accordingly.

    *** Settings ***
    Library    Collections
    
    *** Variables ***
    @{list}
        ...    Kevin_richard
        ...    Dan_ronald
        ...    Daniel_white
        ...    David_jacob
        ...    eddie_bacon
    
    *** Test Cases ***
    Standard Sorting
        ${sorted_list}    Sort List Custom    ${list}
    
        ${result}    Create List
        ...    Dan_ronald
        ...    Daniel_white
        ...    David_jacob
        ...    Kevin_richard
        ...    eddie_bacon    
    
        Lists Should Be Equal    ${sorted_list}    ${result}   
    
    
    Reverse Sorting
        ${alphabet_reverse}    Set Variable    zyxwvutsrqpomnlkjihgfedcbaZYXWVUTSRQPOMNLKJIHGFEDCBA9876543210_${SPACE}
        ${sorted_list}   Sort List Custom    ${list}    ${alphabet_reverse}
    
        ${result}    Create List
        ...    eddie_bacon
        ...    Kevin_richard
        ...    David_jacob
        ...    Daniel_white
        ...    Dan_ronald
    
    
        Lists Should Be Equal    ${sorted_list}    ${result}        
    
    *** Keywords ***
    Sort List Custom
        [Documentation]
        ...    Sort a list using a custom sort order
        ...    
        ...    This keyword sorts a list according to a custom sort order 
        ...    when given, or the default one when not provided. 
        ...    
        ...    Arguments:
        ...    - input_list    {list}      a list of strings to be sorted.
        ...    - alphabeth     {string}    a string of characters according to which order they
        ...                                must be sorted.
        ...    
        ...    Returns:        {list}      the sorted list.
        ...    
        [Arguments]    ${input_list}    ${alphabet}=${SPACE}_0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz
    
        ${ns}    Create Dictionary    alphabet=${alphabet}    input_list=${input_list}
    
        ${sorted}    Evaluate     sorted(input_list, key=lambda word: [alphabet.index(c) for c in word])     namespace=${ns} 
        [Return]    ${sorted}
    

  • answered 2018-11-08 08:37 Todor

    Sort List ignores special characters hence underscore after Dan is skipped and checks for the next alphabet(r vs i).

    That is not so - Sort List does not modify the members in any way, nor it skips any charterers. When it ran, it compared the 'i' to '_' and (somehow) decided 'i' is with a smaller character code than the '_'.
    In fact, the Sort List is just a wrapper over python's sort() method.

    I've ran your source list in a repl, and it came out sorted in the expected way - 'Dan_' before 'Daniel_':

    >>> a = ["Kevin_richard", "Dan_ronald", "Daniel_white", "David_jacob", "eddie_bacon"]
    >>> a
    ['Kevin_richard', 'Dan_ronald', 'Daniel_white', 'David_jacob', 'eddie_bacon']
    >>> a.sort()
    >>> a
    ['Dan_ronald', 'Daniel_white', 'David_jacob', 'Kevin_richard', 'eddie_bacon']
    

    There is something else troubling - in normal sorting "Kevin" should come before "eddie" (the capital latin letters are with codes before the small ones), but that is not the output in your question's body. In fact, your output looks like sorted case-insensitive, something the keyword cannot do for sure.

    Which leads me to think there is more to this:

    • Are you sure the sample list you've pasted is precisely the same as the one you're working with in your code? It could be with Unicode charters that resemble the latin ones (like Cyrillic, there are collisions on the visual outlook on many of them), which were not pasted in the question as-is.
    • Are there any whitespace characters around the source values? If yes, that will influence the sorting (and could explain the 'eddie' case) - strip them before doing the sort, if you want to compare just the names.
    • Is the code sample everything you do to get this result?
    • Finally - I've removed the numbers in front of the values - they would have influenced the sorting a lot, but have to ask - they are not in the source values, right?