Need python implementation to create a random nested CDT structure - python

I need to create a function which should create a nested structure based on the context, query value and context position to query we pass.
So let the function parameters be context, query_val and query_position.
The context to pass would be a list of tuples. Lets take an example:
context = [('list', 1), ('map', 2), ('list’, None)]
query_val = 5
query_position=1
Note: in above example we are using three tuples in the context just for the sake of explanation but it can be more number of tuples too, so code should be generic to handle that.
query_position is 1 in the example which points to second tuple i.e. ('map', 2) which is index 1 of context.
Now we have to create nested structure accordingly. In the context first element is a tuple ('list', 1), so top level should be a list. If we had provide input as map then it top level should have been map. The value 1 in ('list', 1) specifies that from index 1 of the top level we should progress to next level/depth. No of elements at each level should be lets say 5. Other elements apart from index 1 in top level list in the example should be random integers. So second index at top level list should now be a map as the next element in the context was a map i.e ('map', 2). So now second level map should have 5 key/value pairs and should have a key 2 because ('map', 2) was provided in the context. The value for key 2 should now again be a list because we have ('list', None) as the next tuple in the context. Other key/value pairs of this second level map can be simple integers other than 2 with random values. But since the query value provided was 5 so one of the value for one of the keys should be 5 in the map because query position was 1 pointing to second tuple ('map', 2). Since last tuple in context is ('list’, None), there is no index in the tuple(second element in the tuple is None) because its the last level and hence the list can have 5 random integers
Sample output for the example used: [0, {1: 1, 2:[1, 2, 3, 4, 5], 3:3, 4: 5, 5: 6}, 3, 4, 5]
Basically I want to have create random nested cdt structure and use it to validate if the query result was correct or not.
Expecting output: [0, {1: 1, 2:[1, 2, 3, 4, 5], 3:3, 4: 5, 5: 6}, 3, 4, 5]

Related

Python LIFO list/array - shifting data, to replace first input with newest value

My goal is to find the highest high in set of price data. However, im currently struggling to append data to a list in a LIFO order (last in first out) in my for loop looping through large set of data. So for example:
I have a list []
append to list item by item in for loop: list [1, 2, 3, 4, 5]
then I have reached desired list length (in this case 5), I want to shift everything down whilst deleting '1' for example it could go to [2, 3, 4, 5, 1] then replace '1' with '6' resulting in [2, 3, 4, 5, 6]
highs_list = np.array([])
list_length = 50
for current in range(1, len(df.index)):
previous = current - 1
if len(highs_list) < list_length:
np.append(highs_list, df.loc[current, 'high'])
else:
np.roll(highs_list, -1)
highs_list[49] = df.loc[current, 'high']
If you insert 1, 2, 3, 4, 5 and then want to remove 1 to insert 6 then this seems to be a FIFO movement, since the First IN (1) is the First OUT.
Anyhow, standard Python lists allow for this by using append() and pop(0), but the in-memory shift of the elements has time complexity O(n).
A much more efficient tool for this task is collections.deque, which also provides a rotate method to allow exactly the [1,2,3,4,5] => [2,3,4,5,1] transformation.

Auto increment same values in dictionary

I have a dictionary:
{'someKey1': 1, 'someKey2': 1, 'someKey3': 1, 'someKey4': 3, 'someKey5': 4, 'someKey6': 4, 'someKey7': 2}
Output im trying to get is a dictionary with auto incremented values like so:
{'someKey1': 1, 'someKey2': 2, 'someKey3': 3, 'someKey4': 5, 'someKey5': 7, 'someKey6': 6, 'someKey7': 4}
Values in someKey1 - someKey3 don't matter as long as they are in 1-3, meaning someKey1 value can be 3 but 3 cannot repeat as value again in dict.
Basically first dict (yes it has to be a dict) contains order of keys but order can repeat thus i want to order is again with auto increment.
Further explanation:
I have a js object in frontend that contains column names from a table as keys, and in frontend user can pick which column should be in what order. Thus the "somekey" is actually column name, and number is where in postion should said column be placed.
The thing with same number for multiple keys is that user can split one column into multipe ones. Thus i dont care for order as long as they are in the same bracket e.g. someKey1-3 must be in postion 1-3 since they have value 1.
Your result indicates that the original values are used as an assignment order for new sequences. However, there is a factor of randomness to the assignment of keys that have the same initial value which I could not figure out from your explanations. i.e. why are someKey1 and someKey2 receiving 1 and 2 while someKey5 and someKey6 get their new values (7 and 6) in descending order.
So the closest I could come to that result is this:
dict1 = {'someKey1': 1, 'someKey2': 1, 'someKey3': 1, 'someKey4': 3, 'someKey5': 4, 'someKey6': 4, 'someKey7': 2}
dict2 = { k:v for v,(k,_) in enumerate(sorted(dict1.items(),key=lambda kv:kv[1]),1) }
print(dict(sorted(dict2.items()))) # printed in key order to facilitate comparison
{'someKey1': 1, 'someKey2': 2, 'someKey3': 3, 'someKey4': 5, 'someKey5': 6, 'someKey6': 7, 'someKey7': 4}
It should be OK if you really don't care about the values given to keys that originally had the same value.

How Do I Find Whether An Item Is Within A Set Or Not?

I have been having this annoying problem where I have an int, and I want to see if that int has an equivalence in a set. If it does, I don't want it in my "nset" values. However, when I attempt this, which seems pretty straightforward, it acts like the item has not been filtered properly.
Example Logs:
RDM is 8
RDM is not in
{1, 5, 6, 7, 8, 9}
{1, 3, 4, 5, 7, 8}
{2, 5, 6, 7, 8}
Code:
nset = list(range(1, self.n2 + 1))
for i in nset:
if(i in self.valuesInRows[space[0]]):
nset.remove(i)
elif(i in self.valuesInCols[space[1]]):
nset.remove(i)
elif(i in self.valuesInBoxes[self.spaceToBox(space[0], space[1])]):
nset.remove(i)
rdm = -1
while(rdm not in nset):
rdm = random.randint(0, self.n2)
print("RDM {}".format(rdm))
print("RDM is {}".format(rdm))
print("RDM is not in")
print(self.valuesInBoxes[self.spaceToBox(space[0], space[1])])
print(self.valuesInRows[space[0]])
print(self.valuesInCols[space[1]])
print()
return rdm
Any explanation would be fantastic, because I've looked at the documentation and it shows that this is the approach I would want to do, but I seem to be missing something.
You are using list instead of sets. Lists are standard Python data types that store values in a sequence. Sets are another standard Python data type that also stores values. The major difference is that sets, unlike lists or tuples, cannot have multiple occurrences of the same element and store unordered values.
By definition, sets won't allow for duplicate values. In lists, Before inserting the value, you have to check the occurrence by in keyword.
https://docs.python.org/3/reference/expressions.html#membership-test-operations

Most efficient way to add an item and at the same time remove one from a list with a fixed length

I'm parsing some data which can have duplicates. To get rid of them, I use a small list with the last five non-duplicate items and check if the current item is not in the list. I have a solution that works, but there should be a better way. Any ideas?
My current code to achieve this:
activities = []
index = 0
# Open file
# Loop lines (each line is an activity)
# Parse line to activity object
if activity not in activities:
# session is part of SQLAlchemy but this isn't that important
self.session.add(activity)
# The part from here on is the one I want changed
if len(activities) == 5:
activities.pop(index)
activities.insert(index, activity)
if index == 4:
index = 0
else:
index = index + 1
EDIT: The problem is not in removing the duplicates inside this list. This is just to check if the new activity is in one of the last added activities. I'm parsing A LOT of data and checking the new activity against all old ones would be a huge bottleneck. The data is sorted by date and can really have a duplicate just in the last few activities (so I'm checking the last 5). Getting the unique values is not the problem, I'm just asking for a solution that does the same thing as mine already does, but would be better.
collections.deque with limited maxlen will be effective
in the insert+delete operation,
from collections import deque
activities = deque(maxlen=5)
# if len(activities) == 5 then the leftmost item will be removed before the push
activities.push(activity)
but # some code in-between may require some changes as now data is
shifted on each step, changing the indices.
Or
you may prefill activities with Nones and then simply do
activities = [None] * 5
index = 0
# some code in-between
activities[index] = activity
if index == 4:
index = 0
else:
index = index + 1
assuming you have no none-activities)
The answer is to use a different data structure - one which is tailor made for this purpose. Your approach fails if the new item is not a duplicate of one of the most recent five elements.
Instead use a set.
Parse each activity into an object of a class with a __hash__ method, then simply add each new activity into the set as you parse them. This will leave you with a collection containing only the unique objects from your input.
Once you have finished parsing the input, you can convert the set into a list.
s = set()
while more_data_to_parse():
s.add(parse_next_object())
activities = list(s)
For example:
>>> s = set()
>>> for i in [1, 2, 3, 2, 3, 4, 5, 6, 1, 6]:
... s.add(i)
...
>>> activities=list(s)
>>> activities
[1, 2, 3, 4, 5, 6]
>>>
The resulting list won't be in the same order as the original input, but that can be resolved by simply sorting it.
You could use OrderedDict to do the filtering. It would preserve the original order so that result would be in order of first occurrence:
from collections import OrderedDict
items = [3, 5, 6, 2, 5, 6, 1, 7, 8, 2, 3, 6]
items = OrderedDict((x, True) for x in items).keys() # [3, 5, 6, 2, 1, 7, 8]

Make Dictionary From 2 List [duplicate]

This question already has answers here:
How can I make a dictionary (dict) from separate lists of keys and values?
(21 answers)
Closed last year.
Trying to make dictionary with 2 list one being the key and one being the value but I'm having a problem. This is what I have so far:
d={}
for num in range(10):
for nbr in range(len(key)):
d[num]=key[nbr]
Say my key is a list from 1 to 9, and value list is [2,4,0,9,6,6,8,6,4,5].
How do I assign so it that its like {0:2, 1:4, etc...}?
zip() to the rescue!
>>> k = range(1,10) # or some list or iterable of sorts
>>> v = [2,4,0,9,6,6,8,6,4,5]
>>> d = dict(zip(k,v))
>>> d
{1: 2, 2: 4, 3: 0, 4: 9, 5: 6, 6: 6, 7: 8, 8: 6, 9: 4}
>>>
For more details, see zip() built-in function, in Python documentation.
Note, regarding range() and the list of "keys".
The question reads "key is a list from 1 to 9" (i.e. 9 distinct keys) but the value list shows 10 distinct values. This provides the opportunity to discuss two points of "detail":
the range() function in the snippet above will produce the 1 through 9 range, that is because the starting value (1, here), if provided, is always included, whereas the ending value (10, here) is never included.
the zip() function stops after the iteration which includes the last item of the shortest iterable (in our case, omitting '5', the last value of the list)
If you are mapping indexes specifically, use the enumerate builtin function instead of zip/range.
dict(enumerate([2,4,0,9,6,6,8,6,4,5]))
values = [2,4,0,9,6,6,8,6,4,5]
d = dict(zip(range(10), values))
mydict = dict(zip(range(10), [2,4,0,9,6,6,8,6,4,5]))
should be something like
dict(zip(a,b))

Categories

Resources