Trying to get something to work where I randomize 4 objects in an array and randomly select one of those. I need to be able to get the original index number for that chosen object back. Any idea on how I should write this as short as possible?
arrayRandomSongs = []
arrayChosen = []
trackChosen = ""
def randomizeArray(self):
del self.arrayRandomSongs[:] # wipes array of all contents without making a new one
self.arrayRandomSongs = self.arraySongs[:]
random.shuffle(self.arrayRandomSongs)
def chooseListing(self):
del self.arrayChosen[:] # same here
for i in xrange(4):
self.arrayChosen.append(self.arrayRandomSongs[i])
del self.arrayRandomSongs[0:3]
def chooseTrack(self):
self.trackChosen = random.choice(self.arrayChosen)
As you can see I would like to select the arayChosen index number for the trackChosen object, but since it's randomized I don't see how I could do that.
You will have to keep track of indexes before randomizing. Then access the index value from the tracking list after randomizing and selecting an element from the randomized list.
For getting index of an element in list you can do <list>.index(<element>).
Explanation:
Create a copy of arrayRandomSongs before shuffling its elements.
original_arrayRandomSongs = arrayRandomSongs[:]
After getting the value of trackChosen by doing random.choice, use that value to get its index in original list by doing
original_arrayRandomSongs.index(self.trackChosen)
Well you could do something like this
list = [4,1,3,2]
list_with_indices = [(num,i) for i, num in enumerate(list)]
shuffle(list_with_indices)
essentially you keep track of the original index.
Related
I have list like below.
test = ['firstvalue', 'thirdvalue']
I want to insert the some values to the list.
secondvalue at index 1 and fourthvalue at index 3
so the output list looks like below
test = ['firstvalue', 'secondvalue', 'thirdvalue', 'fourthvalue']
I tried the below way but it doesn't work for me
print test.insert(1, "secondvalue")
Is there any alternate way to do this?
The insert function does not return a value, but rather modifies the array used on it. Here's an example:
test = ['firstvalue', 'thirdvalue']
test.insert(1, "secondvalue")
print test
I have a list of dictionaries that is initialised by a call to a function with:
new = {'device_id':name,'device_mac':mac, 'device_ttl':ttl}
dev[0] = new
Thereafter, new entries are appended with:
dev.append(new)
Each dictionary has a time to live (TTL). Once that is reached the dictionary is removed:
for i in dev:
if (i['device_ttl'] == 0):
dev.remove(i)
This all seems fine until the list is completely empty. If I then try and add a new entry with:
dev[0] = new
again, I get a 'list index out of range' error.
I've tried changing the original initialisation with an append to an empty list, but that bombs out immediately with a KeyError: device_id.
The entire function that adds entries is:
# Adds a new device to the list of known devices.
def add_device(dev, num, name, mac, ttl):
new = {'device_id':name,'device_mac':mac, 'device_ttl':ttl}
if (num == 0):
#dev.append(new)
#dev = new
dev[0] = new
else:
dev.append(new)
return (num + 1)
The essential part of the main routine is:
devices = [{}] # Empty list.
num_devices = 0
# Code that determines whether to add to the list or not
num_devices = add_device(devices, num_devices,\
name_long, mac_address, ttl_n)
I don't understand why initialising by appending to an empty list is problematic, nor why what does work to initialise, doesn't work when the list is empty. It is created as empty in the first place!
Is there a better way to initialise or append to an empty list?
The answer was to not declare an empty list of dictionaries ,but just an empty list. A number of respondents pointed out the error but did not elucidate an answer.
Declaring an empty list of dictionaries with:
devices=[{}]
Creates an empty list with an empty dictionary. Assigning the first dictionary with:
dev[0] = new
just replaced the empty dictionary. Hence why the same assignment doesn't work when the list is emptied.
The correct initialisation was to just declare:
devices = []
Adding any dictionary after that, including the first one, is by using an append in the function:
dev.append(new)
Thanks for all of the pointers. I found the answer by switching IDE from Atom to Idle for testing. I have to use Atom as it is the only IDE with the PyCom plugin. Idle flagged the error almost immediately.
I am trying to access an indexed item in a list within a dictionary. The dictionary has two keys, the first being an id key, and then each id has an associated dictionary with a datetime object as the key.
I am filtering through the dictionary as I have done many times before in my code and have a peculiar "list index out of range" error. I know that python starts indexing at 0 and have taken this into account.
I am trying to access the 5th element in a list when I get this error. However if I insert the python debugger into my code I am then able to print this same indexed element that produced the error.
An image of the command prompt when I try to run the code
def plot_histogram(dict, newpath):
norm_res = []
res = [] # should I also plot a histogram of the residual?
for id in dict:
for dt in dict[id]:
import pdb; pdb.set_trace()
if dict[id][dt][5] is not None: # np.nan
norm_res.append(float(dict[id][dt][5])) # Need to exclud None results. But want to exclude them for both
# norm res and res at the same time so that neither result is skewed
res.append(float(dict[id][dt][4])) # unfailry. (?)
f = plt.figure()
sns.distplot(norm_res)
f.savefig(newpath + r'\sns_norm_res_histogram.png', dpi=500)
g = plt.figure()
sns.distplot(res)
g.savefig(newpath + r'\sns_res_histogram.png', dpi=500)
return
I think the error could be to do with the fact that I am trying to access the last element in the list, and sometimes this element is a None type. Does this mean that the list will be shortened in length when the None element is in the last position?
Thank you in advance foe any help.
You get the error because dict[id][dt][5] for some id and some dt does not exist. The one you are able to print when debugging likely has a different id or dt.
This has taken me over a day of trial and error. I am trying to keep a dictionary of queries and their respective matches in a search. My problem is that there can be one or more matches. My current solution is:
match5[query_site] will already have the first match but if it finds another match it will append it using the code below.
temp5=[] #temporary variable to create array
if isinstance(match5[query_site],list): #check if already a list
temp5.extend(match5[query_site])
temp5.append(match_site)
else:
temp5.append(match5[query_site])
match5[query_site]=temp5 #add new location
That if statement is literally to prevent extend converting my str element into an array of letters. If I try to initialize the first match as a single element array I get None if I try to directly append. I feel like there should be a more pythonic method to achieve this without a temporary variable and conditional statement.
Update: Here is an example of my output when it works
5'flank: ['8_73793824', '6_133347883', '4_167491131', '18_535703', '14_48370386']
3'flank: X_11731384
There's 5 matches for my "5'flank" and only 1 match for my "3'flank".
So what about this:
if query_site not in match5: # here for the first time
match5[query_site] = [match_site]
elif isinstance(match5[query_site], str): # was already here, a single occurrence
match5[query_site] = [match5[query_site], match_site] # make it a list of strings
else: # already a list, so just append
match5[query_site].append(match_site)
I like using setdefault() for cases like this.
temp5 = match5.setdefault(query_site, [])
temp5.append(match_site)
It's sort of like get() in that it returns an existing value if the key exists but you can provide a default value. The difference is that if the key doesn't exist already setdefault inserts the default value into the dict.
This is all you need to do
if query_site not in match5:
match5[query_site] = []
temp5 = match5[query_site]
temp5.append(match_site)
You could also do
temp5 = match5.setdefault(query_site, [])
temp5.append(match_site)
Assuming match5 is a dictionary, what about this:
if query_site not in match5: # first match ever
match5[query_site] = [match_site]
else: # entry already there, just append
match5[query_site].append(temp5)
Make the entries of the dictionary to be always a list, and just append to it.
I am trying to set up a function that will query an item for its sub components if those exists and return those else return the item itself.
Imagine an object that can contain more objects within it. To access those objects i would do object.GetSubComponentIds() now if that object contains sub objects it would return a list of those sub objects or EmptyList if there are none. In case that there are sub objects contained within it I want to keep going and then for each subobject i want to check if there are any subobjects contained within them. So for every SubObject.GetSubComponentIds() now if those do not contain anything then i would love to return them while maintaining nested structure of objects that they came from.
object1(contains 3 sub objects)
object2(contains 3 sub object and each sub object contains one more sub object)
object3(does not contain sub objects)
inputlist = [object1, object2]
outputlist = [[obj1sub1, obj1sub2, obj1sub3],[[obj2sub1sub1],[obj2sub2sub1],[obj2sub3sub1]],[obj3]]
I am interested in maintaining that nested list structure that will allow me to always trace back the origin of the sub object. Again, a method to get a sub object list is object.GetSubComponentIds() and it will either return a list or Empty List.
Can anyone help me set up an iterative function to retrieve them. Keep in mind that I do not know whether there are any sub objects contained within an object or haw many levels deep are they. It's basically that if it returns a list i need to check every item on that list for more sub objects.
Thank you in advance
Here's my humble first try:
#unwrap all elements to use with API
elements = []
for i in IN[0]:
elements.append(UnwrapElement(i))
#create element set from python list
elementSet = Autodesk.Revit.DB.ElementSet()
for i in elements:
elementSet.Insert(i)
#convert element set to List[Element]
setForCheck = List[Autodesk.Revit.DB.Element]()
elemIter = elementSet.ForwardIterator()
elemIter.Reset()
while elemIter.MoveNext():
curElem = elemIter.Current
setForCheck.Add(curElem)
#iterate throuh all elements to extract nested elements
setLoop = List[Autodesk.Revit.DB.Element]()
elemSet = List[Autodesk.Revit.DB.Element]()
itemOut = []
counter = 0
while setForCheck.Count >= 1:
setLoop.Clear()
for i in setForCheck:
itemOut.append(i)
if i.GetSubComponentIds().Count >= 1:
elem = Autodesk.Revit.DB.ElementSet()
for j in i.GetSubComponentIds():
elem.Insert(doc.GetElement(j))
elemIterA = elem.ForwardIterator()
elemIterA.Reset()
while elemIterA.MoveNext():
curElemA = elemIterA.Current
setLoop.Add(curElemA)
setForCheck.Clear()
elemIterB = setLoop.GetEnumerator()
elemIterB.Reset()
while elemIterB.MoveNext():
curElemB = elemIterB.Current
setForCheck.Add(curElemB)
counter += 1
if counter > 1000:
break
#Assign your output to the OUT variable
OUT = itemOut
You're using some specific libraries, like Autodesk, that I'm not familiar with. Let me answer your question in terms of an abstract example.
Suppose we're dealing with Thing objects, where Thing is defined as:
class Thing(object):
def __init__(self, name):
self.name = name
self.inside = []
We can make Things and put other things inside of them. The example you give in your post can be written:
ob1 = Thing("ob1")
ob1.inside.extend([Thing("ob1sub1"), Thing("ob1sub2"), Thing("ob1sub3")])
ob2 = Thing("ob2")
for i in xrange(1,4):
name = "ob2sub{}".format(i)
thing = Thing(name)
thing.inside.append(Thing(name + "sub1"))
ob2.inside.append(thing)
ob3 = Thing("ob3")
things = [ob1, ob2, ob3]
This makes a sort of tree. Now we'd like to return a nested list of all of the leaf nodes in the tree:
def search_things(things):
names = []
for thing in things:
if not thing.inside:
names.append(thing)
else:
names.append(search_things(thing.inside))
return names
A test:
>>> search_things(things)
[['ob1sub1', 'ob1sub2', 'ob1sub3'],
[['ob2sub1sub1'], ['ob2sub2sub1'], ['ob2sub3sub1']],
'ob3']
I'll let you transform this to your specific problem, but this is the general idea. Note that the algorithm is recursive, not iterative. You said you wanted an iterative algorithm -- and the above can be written iteratively -- but this gives you the idea.