Converting a list to a set changes element order

后端 未结 11 1119
攒了一身酷
攒了一身酷 2020-11-21 23:26

Recently I noticed that when I am converting a list to set the order of elements is changed and is sorted by character.

Consider this examp

相关标签:
11条回答
  • 2020-11-22 00:10

    Here's an easy way to do it:

    x=[1,2,20,6,210]
    print sorted(set(x))
    
    0 讨论(0)
  • 2020-11-22 00:12

    In mathematics, there are sets and ordered sets (osets).

    • set: an unordered container of unique elements (Implemented)
    • oset: an ordered container of unique elements (NotImplemented)

    In Python, only sets are directly implemented. We can emulate osets with regular dict keys (3.7+).

    Given

    a = [1, 2, 20, 6, 210, 2, 1]
    b = {2, 6}
    

    Code

    oset = dict.fromkeys(a).keys()
    # dict_keys([1, 2, 20, 6, 210])
    

    Demo

    Replicates are removed, insertion-order is preserved.

    list(oset)
    # [1, 2, 20, 6, 210]
    

    Set-like operations on dict keys.

    oset - b
    # {1, 20, 210}
    
    oset | b
    # {1, 2, 5, 6, 20, 210}
    
    oset & b
    # {2, 6}
    
    oset ^ b
    # {1, 5, 20, 210}
    

    Details

    Note: an unordered structure does not preclude ordered elements. Rather, maintained order is not guaranteed. Example:

    assert {1, 2, 3} == {2, 3, 1}                    # sets (order is ignored)
    

    assert [1, 2, 3] != [2, 3, 1]                    # lists (order is guaranteed)
    

    One may be pleased to discover that a list and multiset (mset) are two more fascinating, mathematical data structures:

    • list: an ordered container of elements that permits replicates (Implemented)
    • mset: an unordered container of elements that permits replicates (NotImplemented)*

    Summary

    Container | Ordered | Unique | Implemented
    ----------|---------|--------|------------
    set       |    n    |    y   |     y
    oset      |    y    |    y   |     n
    list      |    y    |    n   |     y
    mset      |    n    |    n   |     n*  
    

    *A multiset can be indirectly emulated with collections.Counter(), a dict-like mapping of multiplicities (counts).

    0 讨论(0)
  • 2020-11-22 00:17

    As denoted in other answers, sets are data structures (and mathematical concepts) that do not preserve the element order -

    However, by using a combination of sets and dictionaries, it is possible that you can achieve wathever you want - try using these snippets:

    # save the element order in a dict:
    x_dict = dict(x,y for y, x in enumerate(my_list) )
    x_set = set(my_list)
    #perform desired set operations
    ...
    #retrieve ordered list from the set:
    new_list = [None] * len(new_set)
    for element in new_set:
       new_list[x_dict[element]] = element
    
    0 讨论(0)
  • 2020-11-22 00:18

    An implementation of the highest score concept above that brings it back to a list:

    def SetOfListInOrder(incominglist):
        from collections import OrderedDict
        outtemp = OrderedDict()
        for item in incominglist:
            outtemp[item] = None
        return(list(outtemp))
    

    Tested (briefly) on Python 3.6 and Python 2.7.

    0 讨论(0)
  • 2020-11-22 00:19

    In case you have a small number of elements in your two initial lists on which you want to do set difference operation, instead of using collections.OrderedDict which complicates the implementation and makes it less readable, you can use:

    # initial lists on which you want to do set difference
    >>> nums = [1,2,2,3,3,4,4,5]
    >>> evens = [2,4,4,6]
    >>> evens_set = set(evens)
    >>> result = []
    >>> for n in nums:
    ...   if not n in evens_set and not n in result:
    ...     result.append(n)
    ... 
    >>> result
    [1, 3, 5]
    
    

    Its time complexity is not that good but it is neat and easy to read.

    0 讨论(0)
提交回复
热议问题