Guest User

Untitled

a guest
Jun 21st, 2018
125
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 3.73 KB | None | 0 0
  1. from copy import copy
  2.  
  3. # allCombinations looks for these to know where there are multiple possibilities
  4. class oneOf(object):
  5. def __init__(self, *options):
  6. self.options = options
  7.  
  8. # signifies that the element shouldn't be there at all. Don't add it to the list,
  9. # the key shouldn't be there, the attribute shouldn't be there, and so forth.
  10. class leaveOut():
  11. pass
  12.  
  13. # needed (I think) for handling dicts; we walk the object many times, so we have to make sure
  14. # that we visit the keys in the same order. There's no guarantee of dict key order in Python
  15. # perhaps there's a guarantee that it'll be the same order per run of the program, but I'm not
  16. # banking on that
  17.  
  18. def order_by_hash(a, b):
  19. h_a = hash(a)
  20. h_b = hash(b)
  21. # for some reason at some points hash(a) - hash(b) always returns 0, but not if you set to variables first.
  22. # also in some cases, the sort function complains that we're returning longs, so we're just going to return -1 or 1
  23. if h_a > h_b:
  24. return 1
  25. else:
  26. return -1
  27.  
  28. # take a list of lists of possibilities for each slot, and returns the list of all possible
  29. # combinations. Sortof hard to explain, here's an example:
  30. #
  31. # combo_helper( [[1, 2], [5, 6], ["a", "b"]] )
  32. # returns
  33. # [ [1,5, "a"], [1,5, "b"], [1,6, "a"], [1,6, "b"], [2,5, "a"], [2,5, "b"], [2,6, "a"], [2,6, "b"] ]
  34.  
  35. def _combo_helper(lst):
  36. if len(lst) == 1:
  37. all_combos = [[x] for x in lst[0]]
  38. else:
  39. lower_combos = _combo_helper(lst[1:])
  40. all_combos = []
  41. for x in lst[0]:
  42. all_combos += [ [x] + combo for combo in lower_combos ]
  43. return all_combos
  44.  
  45.  
  46. # Here's the main function
  47.  
  48. def allCombinations(struct):
  49.  
  50. def walkWith(struct, replace, action):
  51. if isinstance(struct, oneOf):
  52. return action(struct, replace)
  53. elif isinstance(struct, list):
  54. newlist = []
  55. for item in struct:
  56. newitem, replace = walkWith(item, replace, action)
  57. if newitem != leaveOut:
  58. newlist.append(newitem)
  59. return newlist, replace
  60. elif isinstance(struct, tuple):
  61. newlist = [] # using a list because a tuple can't change size
  62. for item in struct:
  63. newitem, replace = walkWith(item, replace, action)
  64. if newitem != leaveOut:
  65. newlist.append(newitem)
  66. return tuple(newlist), replace
  67. elif isinstance(struct, dict):
  68. newdict = {}
  69. sorted_keys = sorted(struct.keys(), order_by_hash) # ensuring the same order every time
  70. for key in sorted_keys:
  71. newval, replace = walkWith(struct[key], replace, action)
  72. if newval != leaveOut:
  73. newdict[key] = newval
  74. return newdict, replace
  75. elif hasattr(struct, "__dict__"):
  76. new_struct = copy(struct)
  77. new_struct.__dict__, replace = walkWith(struct.__dict__, replace, action)
  78. return new_struct, replace
  79. else:
  80. return struct, replace
  81.  
  82. def getReplacements(struct, replace):
  83. replace.append(struct.options)
  84. return None, replace
  85.  
  86. def copyStruct(struct, replace):
  87. return replace[0], replace[1:]
  88.  
  89. _, allreplacements = walkWith(struct, [], getReplacements)
  90. if allreplacements == []:
  91. return [struct]
  92. return [walkWith(struct, replacement, copyStruct)[0] for replacement in _combo_helper(allreplacements)]
  93.  
  94.  
  95. def test1():
  96. class A():
  97. def __repr__(self):
  98. return "A(" + self.__dict__.__repr__() + ")"
  99.  
  100. a = A()
  101. a.x = oneOf(1, leaveOut)
  102. print allCombinations({5:a, 7:oneOf(2, leaveOut)})
  103.  
  104.  
  105.  
  106. def test2():
  107. print allCombinations({5:"a", 7:2})
  108.  
  109. def test3():
  110. print allCombinations([1, oneOf() ])
Add Comment
Please, Sign In to add comment