AS3 Array Object Filtering Question - arrays

I have an array of objects. What I would like to do is get the last index of an object whose property equals a certain value.
Ex:
// this occurs on a mouse click
var stockObj:Object = new Object();
stockObj.ID = "an_id";
stockObj.category = "a_category";
array.push(stockObj);
//psuedo
trace(array.lastIndexOf(stockObj.category=="a_category"));
I would like this to trace the index of the object whose category property equals "a_category"

function searchCategory(arr:Array, cat:String):int {
for (var i:int = arr.length - 1; i >= 0; i--) {
if (arr[i].category == cat) { // assuming array objects contains category
return i;
}
}
return -1; // no match
}

last index of searches on a string not an array:
http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/String.html#lastIndexOf%28%29
what you will need to do is run through the Array which will take O(n) time and compare to see which at which index has the object with category name "a_category"
for(int i = 0;i<array.length;i++){
if(array[i].category = "a_category")
maxIndex = i;
}
}
There is actually a better way to loop through all obj in an array of obj, but I can't remember it atm hopefully someone can comment that in but I think its something like
for (x in array){
...
}
anyways using that logic, it would be a lot faster if you reverse it, so you start at the end of the array and return the index with the first occurrence of the obj with category "a_category"

Related

Why is this comparison between 2 arrays not working, if their contents differ from each other?

I've tried using JSON.stringify() to compare two arrays, I've tried comparing them without JSON.stringify(), but none of the way seems to capture the change in one of the array element. See it highlighted below:
Here's the piece of code I'm running:
var duplicate = false;
loop1:
for (var x = 0; x < data.length; x++) {
loop2:
for (var j = 0; j < pushedDbData.length; j++) {
if (JSON.stringify(data[x].join()) == JSON.stringify(pushedDbData[j].join())) {
duplicate = true;
break loop1;
}
}
}
if (duplicate == true) {
Browser.msgBox('No change has been been made.');
return;
Appreciate your help - as usual!
I understood that from your script, the arrays of data and pushedDbData might be 2 dimensional array. In your script, when the arrays of data and pushedDbData are compared, one element of data is compared with all element of pushedDbData. At this time, when the element of data is the same with one of elements of pushedDbData, duplicate becomes true, even when all other elements are the same. I thought that this might be the reason of your issue.
In order to check the difference of the arrays, how about the following 2 patterns?
Pattern 1:
In this pattern, the arrays of data and pushedDbData are compared with the same index. In this case, each element of data and pushedDbData is compared with the same index. The sample script is as follows.
var res = data.filter((r, i) => pushedDbData[i] && JSON.stringify(r.join()) != JSON.stringify(pushedDbData[i].join()));
console.log(res)
If each element of data and pushedDbData is different with the same index, the length of res is more than 1.
Pattern 2:
In this pattern, the arrays of data and pushedDbData are compared with all elements. In this case, each element of data is compared with all elements of pushedDbData, and the same element and the different element are returned as the object.
var obj = data.reduce((o, r, i) => {
pushedDbData.forEach((s, j) => o[JSON.stringify(s.join()) == JSON.stringify(r.join()) ? "sameElement" : "differentElement"].push({indexOfData: i, indexOfPushedDbData: j}));
return o;
}, {sameElement: [], differentElement: []});
console.log(obj)
In this sample script, the output values are returned as the index of each array.
Note:
From but none of the way seems to capture the change in one of the array element. in your question, I proposed above 2 patterns. When I misunderstood your goal, can I ask you about the sample output you expect? By this, I would like to modify it.
References:
filter()
reduce()
Added:
From your sample Spreadsheet and your current script, how about the following modification?
From
var duplicate = false;
loop1:
for (var x = 0; x < data.length; x++) {
loop2:
for (var j = 0; j < pushedDbData.length; j++) {
console.log(data[x])
if (data[x].join() == pushedDbData[j].join()) {
duplicate = true;
break loop1;
}
}
}
To:
var obj = data.reduce((o, r) => Object.assign(o, {[JSON.stringify(r.join())]: true}), {});
var duplicate = pushedDbData.every(e => obj[JSON.stringify(e.join())]);
In this modified script, at first, an object is created from data for searching the values from pushedDbData. And, when the values of data are not included in pushedDbData, true is returned. Even when only one element is different, false is returned.

Accessing Array Length comes back as Zero

I have an array in ActionScript 3 that is formatted as follows:
var _arrayList = new Array;
_arrayList["item1"] = true;
_arrayList["item2"] = 56;
_arrayList["item3"] = "john doe";
_arrayList["item4"] = -56.8;
and I'm attempting to pull the "_arrayList.Length" but it comes back 0... why?
Because the way you do it makes the array "associative". In Action Script, every class is a basic Object, with dynamic properties. And array does both - containing indexed elements, and having a dynamic properties.
Here's an example of a regular array:
var array:Array = new Array();
array.push(value); // equal to array[0] = value;
array.push(56); // equal to array[1] = value;
array[20] = 'test'; // will put 20th element to be 'test'
If you use this approach, the length of the array will not be 0. And so you can use a for loop:
var total:uint = array.length;
for (var i:uint = 0; i < total; i++) {
trace (array[i]);
}
But when the keys are not numeric, you are actually setting "properties" to the array and thus the length is 0. Again, you can loop through them, but with for-in:
for (var key:String in array) {
trace (array[key]);
}
Here the keys won't be 0, 1, 2, 3 and so on, but instead will be item1, item2, item3. (keep in mind that the order is not preserved!)
So the basic conclusion is that if you use non-numeric keys, then use an Object instead. Array is for numeric indexed collections.

actionscript subtract specific items from array

how do I remove specific items from my array that is hundreds of items long?
-eg:
var myArray:Array = ["dog", "cat", "bear", "duck", "frog", etc..., etc...];
What do I do when I want to remove "duck" from this array? Please keep in mind, that the array is very long and we do not know WHERE the "duck" is, so we don't know it's index in the array.
I need to get that item somehow by it's name and remove it from the array.
myArray.splice(myArray.indexOf("duck"), 1);
This is a straight-forward way of doing it:
Non-stable version (does less copying).
for (var i:int, j:int = array.length - 1, temp:Object; i <= j;) {
temp = array[i];
if (temp == "duck") {
array[i] = array[j];
array[j] = temp;
j--;
} else {
i++;
}
}
array.length = i;
And the stable version (more copying, but the order of the original array is unchanged):
for (var i:int, j:int, temp:Object; i < array.length; i++) {
temp = array[i];
if (temp != "duck") {
array[j] = temp;
j++;
}
}
array.length = j;
However, if you could assure that values are unique, the algorithm would be different, since you wouldn't have to verify items after the one you've found.
The algorithm would be significantly different, if the array was sorted because you could use binary search to find the element to remove. In some very peculiar situations, like, for example, if you have a well-founded set (which is your array), the deletion would be even simpler, because the position of the item you are searching for could be determined in constant time. The later can be mitigated through the use of indices (put simple, you could have a hash-table that uses elements of the array as its keys and their offsets into array as values).
Again, you need to consider all those cases and what is practical with regard to your program.
As I've mentioned above, there may be benefits if you use a different data structure, or if you sort on insert, or if you index on insert.
Lastly, producing a copy with undesired items removed is different from destructively removing items from the same array.
If your array is very long, it is well worth optimizing it somehow.
some options:
1) use a dictionary; the string can be the key. This has the added benefit of not re-indexing your list when you add/remove elements.
//specify weak keys when you create the dictionary
var myDictionary:Dictionary = new Dictionary(true);
//when you want to delete an item:
myDictionary["duck"] = null;
2) sort your array and use a binary search. There's lots of info about binary search online. Here's one SO question on the topic.
One way is to just use a while loop in combination with the indexOf method of an Array as such :
var index:int;
while ((index = myArray.indexOf("duck")) >= 0)
{
myArray.splice(index,1);
}
You could wrap that in a function and accept Array and String parameters, and return the resulting array like this :
function removeSearchString(sourceArray:Array, searchString:String):Array
{
var index:int;
while ((index = sourceArray.indexOf(search)) >= 0)
{
sourceArray.splice(index,1);
}
return sourceArray;
}
then you'd use the function like this :
myArray = removeSearchString(myArray, "duck");

Efficient algorithm for difference of array and a known subsequence?

I'm passing an array to a library function which returns an array which is a subsequence of the input array. That is to say the orders of the first and second array are identical but the second array may be lacking any number of elements of the first array. There will be no duplicates in either array!
I want to then build a new array of all the elements which were in the input but are not in the output of the function.
For some reason though it sounds trivial I keep getting it wrong, especially at the ends of the arrays it seems.
Example 1 (typical):
input array a:
[ yyz, ltn, tse, uln, ist, gva, doh, hhn, vlc, ios, app, tlv, lcy ]
input array b:
[ yyz, ltn, tse, uln, ist, gva, doh, hhn, vlc, tlv, lcy ]
output array "diff":
[ ios, app ]
Example 2 (minimal, reveals some bugs when the difference is at the end of the strings):
input array a:
[ usa ]
input array b:
[ ]
output array "diff":
[ usa ]
(I'm going to implement it in JavaScript / jQuery but I'm more interested in a generic algorithm in pseudocode since I'll actually be dealing with arrays of objects. So please I'm looking for algorithms which specifically use array indexing rather than pointers like I would in C/C++)
As the second array b is a subset of the first array a with the same order, you can walk both in parallel, compare the current values, and take the current value of a if it is different from the current value of b:
var a = ['yyz','ltn','tse','uln','ist','gva','doh','hhn','vlc','ios','app','tlv','lcy'],
b = ['yyz','ltn','tse','uln','ist','gva','doh','hhn','vlc','tlv','lcy'],
diff = [];
var i=0, j=0, n=a.length, m=b.length;
while (i<n && j<m) {
if (a[i] !== b[j]) {
diff.push(a[i]);
} else {
j++;
}
i++;
}
while (i<n) {
diff.push(a[i++]);
}
Or if you prefer just one while loop:
// …
while (i<n) {
if (j<m && a[i] === b[j]) {
j++;
} else {
diff.push(a[i]);
}
i++;
}
In java i would probably do something like this if I hade to use Arrays. You will have to loop over all your objects you get back and you will have to compare them to all of thoese you sent in so you will in the worst case have a O(n^2) complexity I belive, but, you can probably improve this by sorting your list you send in and the use pointers to to check each position (but since you didnt want to use pointers I leave this sample out) then you might be able to compare this in O(n).
public void doYourJob(){
Object[] allObjects = new Object[10]; //hold all original values
Object[] recivedArray = yourBlackBox(allObjects); //send in the array an gets the smaller one
Object[] missingArray = new Object[allObjects.length - recivedArray.length];
for(Object inObj : allObjects){
boolean foundObject = false;
for(Object obj : recivedArray){
if(inObj.equals(obj)){
foundObject = true;
break;
}
}
if(!foundObject)
missingArray add inObj //add the missing object. This is not correct java code. =)
}
}
If I were aloud to use something from the Collection interface then this would be much simpler since you can use a "myArray.contains()" method.
With Lists instead
public void doYourJob(){
List<Object> allObjects = new ArrayList<Object>(); //hold all original values
List<Object> recivedArray = yourBlackBox(allObjects); //send in the array an gets the smaller one
List<Object> missingArray = new ArrayList<Object>();
for(Object inObj : allObjects){
if(!recivedArray.contains(inObj))
missingArray.add(inObj);
}
}
Do you have a guaranteed ordering imposed on your arrays? If so, it should be relatively simple to do something like:
# our inputs are array1 and array2, array2 is the one with 0 or more missing elements
ix1 = 0
ix2 = 0
diff = new array
while ix2 < length(array2)
while (ix1 < length(array1)) and (array1[ix1] != array2[ix2])
add array1[ix1] to diff
ix1 = ix1 + 1
ix1 = ix1 + 1
ix2 = ix2 + i
return diff
If you do not have an ordering, you can either impose one (sort both arrays) or you can use a hash table.
hash = new hash
diff = new array
for each element in array1
hash[element] = 1
for each element in array2
hash[element] = hash[element] + 1
for each key in hash
if hash[key] == 1
add hash[key] to diff
Both of these should run in (roughly) O(n), if (and only if) adding an element to an array is O(1) (if you double the size of the result array every time it gets filled, it's at least asymptotically O(1)).

Why my function doesn't get my int var?! AS3

I have a trouble. I got my dear var myVar:int and an arr:Array. I want to use them to execute my function.
s1 and indice1 are array and integer values as I was defined in my program.
getIndex(s1, indice1);
function getIndex(arr:Array, index:int = 0):void {
for (var n:int = 0; n <= arr.length; n++) {
if (String(arr[n]).indexOf(">") >= 0) {
index = n;
trace(n);
arr[n] = String(arr[n]).substring(1);
}
}
}
now i get rigth results for my Array but i have a 0 for my index var.
Can someone help me?
I mean i need a dynamic way to assing index values of differents arrays to diferents indices so I can use my function to retrieve and index and save it for any Array I have
Your question is pretty unclear.
However, to answer (what I THINK you are asking),
You can not access variable index outside of the function. This is because the type int is not saved as a reference in AS3. To get index outside, you will have to do either of the following:
a) Assign the value of index to a global variable e.g.:
var gIndex:int;
function getIndex(arr:Array,index:int = 0):void{
//function contents
gIndex=index;
}
//This way you can access index as gIndex;
b) Return the variable index from the function
function getIndex(arr:Array,index:int = 0):int{
//function contents
return index;
}
//this way you can access index as getIndex(s1, indice1);
Your search string is available in arr[0] So that it returns 0.
Ok, I solve it.
Well it isn't what I want to but look.
I decided to return n value from my function and assing it to my var.
indice1 = getIndex(s1);
function getIndex(arr:Array){
for(var n:int=0; n<= arr.length; n++){
if( String(arr[n]).indexOf(">") >= 0){
return n;
arr[n]= String(arr[n]).substring(1);
}
}
}
So I got n value on my var and that's it. thanks Anyway =D

Resources