finding an array element
Moderators: FourthWorld, heatherlaine, Klaus, kevinmiller
finding an array element
Given this array:
put 15 into myArr[1]
put 16 into myArr[2]
put 17 into myArr[3]
how do I find the position of 16 in that array (which is 2)?
I know I can loop through the array looking for 16, but there's probably a more efficient way...
Slava
put 15 into myArr[1]
put 16 into myArr[2]
put 17 into myArr[3]
how do I find the position of 16 in that array (which is 2)?
I know I can loop through the array looking for 16, but there's probably a more efficient way...
Slava
-
- VIP Livecode Opensource Backer
- Posts: 9580
- Joined: Wed May 06, 2009 2:28 pm
- Location: New York, NY
Re: finding an array element
Try this:
This should get you started,
Craig Newman
Code: Select all
on mouseUp
put 15 into myArr[1]
put 16 into myArr[2]
put 17 into myArr[3]
combine myArr by return and comma
answer myArr
end mouseUp
This should get you started,
Craig Newman
Re: finding an array element
Thanks, Craig, but that's not what I asked.
The handler you kindly suggested lists the contents of the array.
I am looking for a way to determine the position of an element with a certain value. E.g., the value of the second element is 16. I want a function like myArr.getPos(16) that would return 2.
I couldn't find the answer in the section on arrays in the User Guide, and all the terms I tried to look up in the Dictionary turned out to be bad guesses. With the English-like synatx of LC, I don't know what to look for.
I can probably write my own function along the lines of
but that would hardly be efficient. I'm sure the language has what I'm looking for... doesn't it?
The handler you kindly suggested lists the contents of the array.
I am looking for a way to determine the position of an element with a certain value. E.g., the value of the second element is 16. I want a function like myArr.getPos(16) that would return 2.
I couldn't find the answer in the section on arrays in the User Guide, and all the terms I tried to look up in the Dictionary turned out to be bad guesses. With the English-like synatx of LC, I don't know what to look for.
I can probably write my own function along the lines of
Code: Select all
function getPos aArr, aVal
repeat with i = 1 to the number of elements in aArr
if aArr[i] is aVal then
return i
end if
end repeat
end getPos
Re: finding an array element
Craig was pretty close:
I'm not saying that this is efficient. For more complex searches, you'll have to replace (item 2 of each is 16) with a custom function. This might make it rather slow. Looping through all elements of the array might be faster, depending on the complexity of the search.
Kind regards,
Mark
Code: Select all
on mouseUp
put 15 into myArr[1]
put 16 into myArr[2]
put 17 into myArr[3]
combine myArr by cr and comma
sort lines of myArr by (item 2 of each is 16)
put item 1 of last line of myArr into myPos
answer myPos
end mouseUp
Kind regards,
Mark
The biggest LiveCode group on Facebook: https://www.facebook.com/groups/livecode.developers
The book "Programming LiveCode for the Real Beginner"! Get it here! http://tinyurl.com/book-livecode
The book "Programming LiveCode for the Real Beginner"! Get it here! http://tinyurl.com/book-livecode
Re: finding an array element
Thanks, Mark. I can't believe the language has no built-in function to find an element in an array by its value. Every other language I know does. Perhaps I am on the wrong track altogether, and an array is simply not used for that kind of thing in LC?
Suppose you have two lists of values, and you need a conversion routine. Let's say you are building your own function for converting upper case characters to lower case. You have 32,000 pairs of letters. For examle, you know that the character whose decimal code point is 1234 happens to be the upper case leetter for the character whose decimal code point is 1268. You have two decimal numbers for each upper case/lower case pair.
One way to do that is to set two arrays such that element N of array UpperCaceArr is the upper case equivalent of element N of array LowerCaseArr. Then, given any character's code point you can find its position in one of these arrays, and presto! the corresponding element of the other array is its upper/lower case equivalent.
There are countless situations where the ability to find the position of a certain value within an array is useful. If arrays in LC aren't built for those operations, then what is?
Slava
Suppose you have two lists of values, and you need a conversion routine. Let's say you are building your own function for converting upper case characters to lower case. You have 32,000 pairs of letters. For examle, you know that the character whose decimal code point is 1234 happens to be the upper case leetter for the character whose decimal code point is 1268. You have two decimal numbers for each upper case/lower case pair.
One way to do that is to set two arrays such that element N of array UpperCaceArr is the upper case equivalent of element N of array LowerCaseArr. Then, given any character's code point you can find its position in one of these arrays, and presto! the corresponding element of the other array is its upper/lower case equivalent.
There are countless situations where the ability to find the position of a certain value within an array is useful. If arrays in LC aren't built for those operations, then what is?
Slava
Re: finding an array element
Hi Slava,
If you have two corresponding lists of values, you'd save them as separate lists. Get the lineoffset of a value in one list and find the line with that lineoffset in the second list. Let's assume you keep the two lists of characters in fields.
put line lineoffset(myChar,fld "List 1") of fld "List 2" into myNewChar
No arrays involved.
Kind regars,
Mark
If you have two corresponding lists of values, you'd save them as separate lists. Get the lineoffset of a value in one list and find the line with that lineoffset in the second list. Let's assume you keep the two lists of characters in fields.
put line lineoffset(myChar,fld "List 1") of fld "List 2" into myNewChar
No arrays involved.
Kind regars,
Mark
The biggest LiveCode group on Facebook: https://www.facebook.com/groups/livecode.developers
The book "Programming LiveCode for the Real Beginner"! Get it here! http://tinyurl.com/book-livecode
The book "Programming LiveCode for the Real Beginner"! Get it here! http://tinyurl.com/book-livecode
Re: finding an array element
Thanks, Mark. You've been very helpful. So you're assuming I have my 32,000 decimal numbers in a text field, one number per line, and lineoffset() will search that text field. I was thinking that an array of integers would be more efficient, but I'll experiment with this. I don't really needs 32,000 numbers, that was only an example. And I didn't know enough to think of lineoffset.
Thanks also for your response to my Unicode question. I'll exsperiment with that, and I'm sure I'll have more postings on Unicode.
Perhaps I should explain what I am doing and why I'm in the summer academy, learning CL.
I am porting my Adobe Director application. It is a Russian dictionary for students. The data is in a SQLite database. The student will run searches and view the entries--that's it. Very simple. The db has a look-up index table where each word points to an entry in another table. 250,000 records in the lookup table, and 17,000 records in the entries table. All entries are stored as fairly simple HTML, for easy display and formatting. Cyrillic characters are stored as UTF-8 text, not as HTML entities.
So my first CL application has to:
1) accept user's input, a typed string;
2) the user will be typing with her English keyboard, so before displaying what she types in Cyrilic, the field must remap the keyboard input, e.g. when the user types the English lower case "a" the field must receive and display the Russian "a" which is 1072 decimal in Unicode;
3) because the user might type punctuation, upper and lower case letters, and accented letters, the CL script must normalize the input, i.e. remove all illegal characters and convert upper case and accented letters to their lowwer case unaccented equivalents. The normalized string need not be displayed.
4) look up the normalized string in the look-up table (i. e. run a SELECT query)
5) retrieve the matching enrties from the other table; they are in HTML format, full of Unicode Cyrillic and English text
6) display the HTML by assigning it to a field.
I am trying to learn how to do this. Since I've already done it in Director, I'm probably going through a very convoluted learning curve
Gratefully,
Slava
Thanks also for your response to my Unicode question. I'll exsperiment with that, and I'm sure I'll have more postings on Unicode.
Perhaps I should explain what I am doing and why I'm in the summer academy, learning CL.
I am porting my Adobe Director application. It is a Russian dictionary for students. The data is in a SQLite database. The student will run searches and view the entries--that's it. Very simple. The db has a look-up index table where each word points to an entry in another table. 250,000 records in the lookup table, and 17,000 records in the entries table. All entries are stored as fairly simple HTML, for easy display and formatting. Cyrillic characters are stored as UTF-8 text, not as HTML entities.
So my first CL application has to:
1) accept user's input, a typed string;
2) the user will be typing with her English keyboard, so before displaying what she types in Cyrilic, the field must remap the keyboard input, e.g. when the user types the English lower case "a" the field must receive and display the Russian "a" which is 1072 decimal in Unicode;
3) because the user might type punctuation, upper and lower case letters, and accented letters, the CL script must normalize the input, i.e. remove all illegal characters and convert upper case and accented letters to their lowwer case unaccented equivalents. The normalized string need not be displayed.
4) look up the normalized string in the look-up table (i. e. run a SELECT query)
5) retrieve the matching enrties from the other table; they are in HTML format, full of Unicode Cyrillic and English text
6) display the HTML by assigning it to a field.
I am trying to learn how to do this. Since I've already done it in Director, I'm probably going through a very convoluted learning curve
Gratefully,
Slava
-
- VIP Livecode Opensource Backer
- Posts: 7215
- Joined: Sat Apr 08, 2006 8:31 pm
- Location: Minneapolis MN
- Contact:
Re: finding an array element
There may be a crafty way to do what you want, but I think you'll be surprised at just how fast "repeat for each" really is. It can easily process tens of thousands of items in a few milliseconds. In fact, it's so fast that it is usually the preferred way -- it beats out a number of other methods in most benchmarking tests. I'd try benchmarking a "repeat for each" loop that iterates through all the array elements and see if it's fast enough for you.
Jacqueline Landman Gay | jacque at hyperactivesw dot com
HyperActive Software | http://www.hyperactivesw.com
HyperActive Software | http://www.hyperactivesw.com
Re: finding an array element
In his May 14 response, Mark said:
1073
1046
1024
986
106
104
etc.
and the decimal point of myChar happens to be 104, then lineoffset(myChar,fld "List 1") will return 2, because everything is a string, and all comparisons are by text chunks, and "104" is part of string "1046," which is in line 2. The correct value should be 6, because 104 is on the sixths line.
If using this method, I would have to look for the lineoffset by matching the entire line to my target, not a portion of it. If we dealt with numbers instead of strings (in an array or a list), 1046 would not be considered a match for 104.
Is there a way to achieve that?
Thanks,
Slava
I think Mark overlooked my assignment: the two lists (I wanted arrays, but Mark suggested lists) hold the decimal code points of the alphabetic characters, not the characters themselves. If List 1 starts like this:If you have two corresponding lists of values, you'd save them as separate lists. Get the lineoffset of a value in one list and find the line with that lineoffset in the second list. Let's assume you keep the two lists of characters in fields.
put line lineoffset(myChar,fld "List 1") of fld "List 2" into myNewChar
1073
1046
1024
986
106
104
etc.
and the decimal point of myChar happens to be 104, then lineoffset(myChar,fld "List 1") will return 2, because everything is a string, and all comparisons are by text chunks, and "104" is part of string "1046," which is in line 2. The correct value should be 6, because 104 is on the sixths line.
If using this method, I would have to look for the lineoffset by matching the entire line to my target, not a portion of it. If we dealt with numbers instead of strings (in an array or a list), 1046 would not be considered a match for 104.
Is there a way to achieve that?
Thanks,
Slava
Re: finding an array element
After some benchmarking, as jacque suggested, I think the "repeat for each" loop through the entire list of numbers is very practical. Thanks, everybody!
Slava
Slava
Re: finding an array element
Hi there,
You may have already found this, but it's worth mentioning- setting the wholeMatches to true achieves the whole line matching you want. From the dictionary, wholeMatches:
Michael
You may have already found this, but it's worth mentioning- setting the wholeMatches to true achieves the whole line matching you want. From the dictionary, wholeMatches:
Regards,Summary:
Specifies whether the lineOffset, wordOffset, and itemOffset functions search only for entire lines, words, or items.
Examples:
set the wholeMatches to true
Use the wholeMatches property to find lines, words, or items in a container only if what you're searching for matches an entire line, word, or item.
Michael
Re: finding an array element
Thanks, Michael! Yes, this works great, too. S.
Re: finding an array element
Here is the function and a working example for finding the position (key) of an element with a certain value in a 2D Array.
The code:
function getPosOfValueInArray aArr, aVal
repeat with i = 1 to the number of lines in the keys of aArr
if aArr["Idea ID"] = aVal then
return i
end if
end repeat
end getPosOfValueInArray
You may wish to use a parameter for the name of the column: "Idea ID" eg aHeading:
The code:
function getPosOfValueInArray aArr, aVal
repeat with i = 1 to the number of lines in the keys of aArr
if aArr["Idea ID"] = aVal then
return i
end if
end repeat
end getPosOfValueInArray
You may wish to use a parameter for the name of the column: "Idea ID" eg aHeading:
- Attachments
-
- Find Position Of Value In 2D Array.livecode.zip
- (5.98 KiB) Downloaded 86 times
Re: finding an array element
Better late than never, right?
Re: finding an array element
Yes yes, late is fine
Good for people learning!
Although i'm surprised no one mentioned the filter option for doing this - much easier and simpler.
Calling
will put '2' in the message box, as per the OP. If there are multiple keys containing this value, it will return a return-delimited list.
I really do love using filter for arrays - the 'each' keyword is the special sauce... no need for messy iterations
Stam
Good for people learning!
Although i'm surprised no one mentioned the filter option for doing this - much easier and simpler.
Code: Select all
function findIndexOfElementContaining pValue, pArray
filter elements of pArray where each = pValue
return the keys of pArray
end findIndexOfElementContaining
Code: Select all
put findIndexOfElementContaining(16, myArr)
I really do love using filter for arrays - the 'each' keyword is the special sauce... no need for messy iterations
Stam