How to loop on complex list items in Apple Script - applescript

I need to loop over this list.
I can see that apple script knows the length of the list and loop 2 times, but I get an error when I try to access and work with items of list1 :
"Impossible to get item 1 of {BOB:{name:"Bob", place:"london"},
BILL:{name:"Bill", place:"paris"}}"
Here is the code :
set list1 to {BOB:{name:"Bob", place:"london"}, BILL:{name:"Bill", place:"paris"}}
log length of list1
repeat with myItem in list1
log myItem
end repeat
Any idea how to achieve that ?
If the list is a simple one like {"Bob", "Bill"}, it works correctly.
Thanks

It works if list1 is casted as a list
set list1 to {BOB:{name:"Bob", place:"london"}, BILL:{name:"Bill", place:"paris"}}
log length of list1
repeat with myItem in list1 as list
log myItem
end repeat

Related

Filtering in VBA

I am stuck on something and can't see where I have gone wrong.
I have a spreadsheet and will use a command button to filter the spreadsheet based on selected criteria. I have added data validation dropdowns in cells D2 and E2 for the end user to select the options to filter. When selected, the code should hide all rows that do not meet both criteria. Below is the beginning of my code (there will be more steps to follow with summing and format, but this is the first and critical step). When I have tested this so far, I have gotten an "Argument Not Optional" error. I have gone down a rabbit hole trying to figure out where I have gone wrong, but no luck. Any ideas?
Sub Button14_Click(ByVal Target As Range)
ActiveSheet.Unprotect Password:="1234"
If Target.Row = 2 Then
Dim list1 As String, list2 As String
list1 = Range("D2")
list2 = Range("E2")
If list1 = "Construction Contingency" And list2 = "Open" Then
Sheets("UseLog").Range ("A12:J1010")
.AutoFilter Field:=5, Criteria1:=list1
.AutoFilter Field:=6, Criteria2:=list2
End With

How to find the number of items in a variable? (AppleScript)

I am trying to find the number of items in a variable, I tried to create somewhat of a while loop to test if the item of the variable exists, if it does then go to the next item and test if it exists, this repeats until the item does not exist, then it displays the current item number, which should be the final item of the variable.
Here is my code:
set stuff to "123456789"
set x to "1"
set num to item x of stuff
if exists item x of stuff then
repeat while exists item (x + 1) of stuff
if exists (item x of stuff) then
set x to (x + 1)
else
set num to x
end if
end repeat
end if
display dialog num
Currently when I run this code I get the error:
"Can’t get item 10 of "123456789"."
Which I understand tells me that 10 is the last item of this variable but the information does me no good in the form of an error message. Thanks in advance
How to find the number of items in a variable? (AppleScript)
The clue's in the question:
set variable to "123456789"
return the number of items in the variable --> 9
As already stated by red_menace, you can also quantify data objects using the length property (for list, record, or text objects), or by using the count command, which is superfluous in my view as it ends up accessing the length property anyway.
The AppleScript command count counts the number of elements in an object, for example count of stuff. In addition, classes such as list, record, and text also have a length property, for example length of stuff.
set stuff to "this is a test"
set x to 0
repeat with anItem in (get items of stuff)
set x to x + 1 -- just using x to count
log anItem
end repeat
display dialog "Number of items is " & x & return & "Count is " & (count stuff) & return & "Length is " & (length of stuff)
See the AppleScript Language Guide for more information.

Sort dict by second value in tuple and return dict

from collections import defaultdict,OrderedDict
tt=defaultdict (list)
tt={'abcd':(23,77),'ddef':(55,22)}
c=OrderedDict (sorted (tt.items (),key=lambda t: t[1][1]))
print (c)
d=list ((k,v) for k,v in c.items())
print (d)
This sorts correctly for c.
List makes the dict from the OrderedDict
d gets {'ddef':(55,22),'abcd':(23,77)}
Modified the code. Works fine now.
I need to display top (n) keys in a sorted order by the second element of the tuple.
Dict seems to be the best route, there are only ever 50 items in the list,I need the top ten in order.

how to print a dictionary sorted by a value of a subdictionary?

I have a dictionary inside a dictionary and I wish to print the whole dictionary but sorted around a value in the sub dictionary
Lesson = {Name:{'Rating':Rating, 'Desc':Desc, 'TimeLeftTask':Timeleft}}
or
Lesson = {'Math':{'Rating':11, 'Desc':'Exercises 14 and 19 page 157', 'TimeLeftTask':7}, 'English':{'Rating':23, 'Desc':'Exercise 5 page 204', 'TimeLeftTask':2}}
I want to print this dict for example but sorted by 'Rating' (high numbers at the top)
I have read this post but i don't fully understand it.
If you could keep it simple it would be great.
And yes i'm making a program to sort and deal with my homework
Thanks in advance
def sort_by_subdict(dictionary, subdict_key):
return sorted(dictionary.items(), key=lambda k_v: k_v[1][subdict_key])
Lesson = {'Math':{'Rating':11, 'Desc':'Exercises 14 and 19 page 157', 'TimeLeftTask':7}, 'English':{'Rating':23, 'Desc':'Exercise 5 page 204', 'TimeLeftTask':2}}
print(sort_by_subdict(Lesson, 'Rating'))
As there is no notion of order in dictionary, we need to represent the dictionary as a list of key, value pair tuples to preserve the sorted order.
The so question you mention sorts the dictionary using the sorted function such that it returns a list of (k, v) tuples (here k means key & v means value) of top level dictionary, sorting by the desired value of sub dictionary v.

Data structure optimized for adding items (at end of list), iterating, and removing items

I need a data structure which will support the following operations in a performant manner:
Adding an item to the end of the list
Iterating through the list in the order the items were added to it (random access is not important)
Removing an item from the list
What type of data structure should I use? (I will post what I am currently thinking of as an answer below.)
You should use a linked list. Adding an item to the end of the list is O(1). Iterating is easy, and you can remove an item from any known position in the list in O(1) as well.
It sounds like a linked list, however there's a catch you need to consider. When you say "removing an item from the list", it depends on whether you have the "complete item" to remove, or just its value.
I will clarify: let's say your values are strings. You can construct a class/struct containing a string and two linking pointers (forwards and backwards). When given such a class, it's very easy to remove it from the list in O(1). In pseudo code, removing item c looks like this (please disregard validation tests):
c.backwards = c.forwards
if c.backwards = null: head = c.forwards
if c.forwards = null: tail = c.backwards
delete c
However, if you wish to delete the item containing the string "hello", that would take O(n) because you would need to iterate through the list.
If that's the case I would recommend using a combination of a linked list and and hash table for O(1) lookup. Inserting to the end of the list (pseudo code):
new_item = new Item(value = some_string, backwards = tail, forwards = null)
tail.forwards = new_item
tail = new_item
hash.add(key = some_string, value = new_item)
Scanning through the list is just scanning through the linked list, no problems:
i = head
while i != null:
... do something with i.value ...
i = i.forwards
Removing an item from the list by value (pseudo code, no validation testing):
item_to_remove = hash.find_by_key(some_string)
if (item_to_remove != null):
hash.delete_key(some_string)
item_to_remove.backwards = item_to_remove.forwards
if item_to_remove.forwards = null: tail = item_to_remove.backwards
if item_to_remove.backwards = null: head = item_to_remove.forwards
delete item_to_remove
I am thinking of using a simple list of the items. When a new item is added I will just add it to the end of the list. To remove an item, I won't actually remove it from the list, I will just mark it as deleted, and skip over it when iterating through the items.
I will keep track of the number of deleted items in the list, and when more than half of the items are deleted, I will create a new list without the deleted items.
Circular & Doubly-Linked List. It satisfies all 3 requirements:
Adding an item to the end of the list: O(1). By add to Head->prev. It supports Iterating through the list in the same order in which they were added. You can remove any element.
Assuming Java (other languages have similar structures, but I found the JavaDocs first):
ArrayList if you have the index of the item you want to delete
LinkedHashMap if you only have the item and not its position

Resources