actionscript subtract specific items from array - arrays

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");

Related

Actionscript 3: Identifying an array element to delete when the elements are objects/class instances

I have an array of objects, some of which are movieclips and some instances of classes. I need to remove an item from the array but are struggling with how best to identify which array index to delete.
I am currently using this code, which does work
var i:int;
for (i = 0; i < list.length; i++) {
if (list[i].toString() == '[object myClass]') {
trace('found', i);
list.removeAt(i);
}
}
I am thinking a better way must exist to get the object name and without looping through the array.
I could use a little clarification on how you want to identify the object(s) that should be removed. If you are looking to simply remove any object that is an instance of the myClass class, I would recommend the is keyword.
Also, a warning, removing items from a list as you are iterating over it is just asking for trouble. If you remove object at index [0] then the object that used to be at index [1] is now index [0], but your for loop is going to increment i by one at the end of each iteration, so you will never check index [0] again. Thus you may skip one or more of the objects that you wanted to remove.
Instead try iterating over it backwards-- that should resolve that problem.
Here is what both of those recommendations together looks like:
for (var i:int = (list.length - 1); i >= 0; i--)
{
if (list[i] is myClass)
{
trace("found", i);
list.removeAt(i);
}
}

How can i set all items of an array to 0 in GameMaker studio?

Simple. I Need Help Setting All The Values Of An array to 0 in GameMaker: Studio.
This is because i need to test if i have not modified the array by using
if array[id] != 0 {
//Enter code
}
Of course, there are several ways, choose the best depending on the circumstances.
If you haven't filled anything in the array yet, adding a new item to a certain index initializes all previous values with "0":
var array;
array[length-1] = 0; //everything upto length-1 is filled
If you did already create the array and wish to reset it you should loop over it:
for (var i = array_get_length_1d(array) - 1; i >= 0; --i) {
array[i] = 0;
}
If you do not care about the original memory locations, and you can create a complete new array, creating a new one in place of the old one can be slightly faster:
array = 0; //destroys the old array
array[length - 1] = 0; //recreates like in the first option

Swift Dictionary of Arrays

I am making an app that has different game modes, and each game mode has a few scores. I am trying to store all the scores in a dictionary of arrays, where the dictionary's key is a game's id (a String), and the associated array has the list of scores for that game mode. But when I try to initialize the arrays' values to random values, Swift breaks, giving me the error below. This chunk of code will break in a playground. What am I doing wrong?
let modes = ["mode1", "mode2", "mode3"]
var dict = Dictionary<String, [Int]>()
for mode in modes
{
dict[mode] = Array<Int>()
for j in 1...5
{
dict[mode]?.append(j)
let array:[Int] = dict[mode]!
let value:Int = array[j] //breaks here
}
}
ERROR:
Execution was interrupted, reason: EXC_BAD_INSTRUCTION(code=EXC_I386_INVOP, subcode=0x0).
Your problem is array subscripts are zero-based. So when you write:
var a: [Int] = []
for i in 1...5 {
a.append(42)
println(a[i])
}
you will get a runtime error, because first time around the loop you are subscripting a[1] when there is only an a[0]. In your code, you either need to do for j in 0..<5 or let value = array[j-1].
By the way, even though it’s perfectly safe to do dict[mode]! (since you just added it), it’s a habit best avoided as one of these days your code won’t be as correct as you think, and that ! will explode in your face. There’s almost always a better way to write what you want without needing !.
Also, generally speaking, whenever you use array subscripts you are risking an accidental screw-up by accidentally addressing an out-of-bounds index like here. There are lots of alternatives that mean actually using a[i] is easy to avoid:
If you want the indices for a collection (like an array), instead of:
for i in 0..<a.count { }
you can write
for i in indices(a) { }
If you want to number the elements in an array, instead of
for i in indices(a) { println("item \(i) is \(a[i])" }
you can write
for (i, elem) in enumerate(a) { println("item \(i) is \(elem)") }
If the collection happens to have an Int for an index (such as Array), you can use i as an index, but if it doesn’t (such as String) an alternative to get the index and element is:
let s = "hello"
for (idx, char) in Zip2(indices(s),s) { }
If you want the first or last element of an array, instead of:
if a.count > 0 { let x = a[0] }
if a.count > 0 { let x = a[a.count - 1] }
you can write
if let first = a.first { let x = first }
if let last = a.last { let x = first }
Prefer map, filter and reduce to for loops in general (but don’t obsess over it, sometimes a for loop is better)

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)).

How do I remove duplicate strings from an array in C?

I have an array of strings in C and an integer indicating how many strings are in the array.
char *strarray[MAX];
int strcount;
In this array, the highest index (where 10 is higher than 0) is the most recent item added and the lowest index is the most distant item added. The order of items within the array matters.
I need a quick way to check the array for duplicates, remove all but the highest index duplicate, and collapse the array.
For example:
strarray[0] = "Line 1";
strarray[1] = "Line 2";
strarray[2] = "Line 3";
strarray[3] = "Line 2";
strarray[4] = "Line 4";
would become:
strarray[0] = "Line 1";
strarray[1] = "Line 3";
strarray[2] = "Line 2";
strarray[3] = "Line 4";
Index 1 of the original array was removed and indexes 2, 3, and 4 slid downwards to fill the gap.
I have one idea of how to do it. It is untested and I am currently attempting to code it but just from my faint understanding, I am sure this is a horrendous algorithm.
The algorithm presented below would be ran every time a new string is added to the strarray.
For the interest of showing that I am trying, I will include my proposed algorithm below:
Search entire strarray for match to str
If no match, do nothing
If match found, put str in strarray
Now we have a strarray with a max of 1 duplicate entry
Add highest index strarray string to lowest index of temporary string array
Continue downwards into strarray and check each element
If duplicate found, skip it
If not, add it to the next highest index of the temporary string array
Reverse temporary string array and copy to strarray
Once again, this is untested (I am currently implementing it now). I just hope someone out there will have a much better solution.
The order of items is important and the code must utilize the C language (not C++). The lowest index duplicates should be removed and the single highest index kept.
Thank you!
The typical efficient unique function is to:
Sort the given array.
Verify that consecutive runs of the same item are setup so that only one remains.
I believe you can use qsort in combination with strcmp to accomplish the first part; writing an efficient remove would be all on you though.
Unfortunately I don't have specific ideas here; this is kind of a grey area for me because I'm usually using C++, where this would be a simple:
std::vector<std::string> src;
std::sort(src.begin(), src.end());
src.remove(std::unique(src.begin(), src.end()), src.end);
I know you can't use C++, but the implementation should essentially be the same.
Because you need to save the original order, you can have something like:
typedef struct
{
int originalPosition;
char * string;
} tempUniqueEntry;
Do your first sort with respect to string, remove unique sets of elements on the sorted set, then resort with respect to originalPosition. This way you still get O(n lg n) performance, yet you don't lose the original order.
EDIT2:
Simple C implementation example of std::unique:
tempUniqueEntry* unique ( tempUniqueEntry * first, tempUniqueEntry * last )
{
tempUniqueEntry *result=first;
while (++first != last)
{
if (strcmp(result->string,first->string))
*(++result)=*first;
}
return ++result;
}
I don't quite understand your proposed algorithm (I don't understand what it means to add a string to an index in step 5), but what I would do is:
unsigned int i;
for (i = n; i > 0; i--)
{
unsigned int j;
if (strarray[i - 1] == NULL)
{
continue;
}
for (j = i - 1; j > 0; j--)
{
if (strcmp(strarray[i - 1], strarray[j - 1]) == 0)
{
strarray[j - 1] = NULL;
}
}
}
Then you just need to filter the null pointers out of your array (which I'll leave as an exercise).
A different approach would be to iterate backwards over the array and to insert each item into a (balanced) binary search tree as you go. If the item is already in the binary search tree, flag the array item (such as setting the array element to NULL) and move on. When you've processed the entire array, filter out the flagged elements as before. This would have slightly more overhead and would consume more space, but its running time would be O(n log n) instead of O(n^2).
Can you control the input as it is going into the array? If so, just do something like this:
int addToArray(const char * toadd, char * strarray[], int strcount)
{
const int toaddlen = strlen(toadd);
// Add new string to end.
// Remember to add one for the \0 terminator.
strarray[strcount] = malloc(sizeof(char) * (toaddlen + 1));
strncpy(strarray[strcount], toadd, toaddlen + 1);
// Search for a duplicate.
// Note that we are cutting the new array short by one.
for(int i = 0; i < strcount; ++i)
{
if (strncmp(strarray[i], toaddlen + 1) == 0)
{
// Found duplicate.
// Remove it and compact.
// Note use of new array size here.
free(strarray[i]);
for(int k = i + 1; k < strcount + 1; ++k)
strarray[i] = strarray[k];
strarray[strcount] = null;
return strcount;
}
}
// No duplicate found.
return (strcount + 1);
}
You can always use the above function looping over the elements of an existing array, building a new array without duplicates.
PS: If you are doing this type of operation a lot, you should move away from an array as your storage structure, and used a linked list instead. They are much more efficient for removing elements from a location other than the end.
Sort the array with an algorithm like qsort (man 3 qsort in the terminal to see how it should be used) and then use the function strcmp to compare the strings and find duplicates
If you want to mantain the original order you could use a O(N^2) complexity algorithm nesting two for, the first each time pick an element to compare to the other and the second for will be used to scan the rest of the array to find if the chosen element is a duplicate.

Resources