/** Array.c Global array helper functions. @author Zapper, Sven2 */ // Concatenates two arrays and returns a new array. global func Concatenate(array first, array second) { var len_first = GetLength(first); var result = CreateArray(len_first+GetLength(second)); result[:len_first] = first; result[len_first:] = second; return result; } // Returns a new array that contains the values of the first array minus the values of the second array. global func Subtract(array subject, array subtract) { var diff = []; for (var obj in subject) { var removed = false; for (var rem_obj in subtract) { if (rem_obj == obj) { removed = true; break; } } if(!removed) diff[GetLength(diff)] = obj; } return diff; } // Removes nil values from an array, returns the amount of values removed. global func RemoveHoles(array leerdammer) { var move = 0; var len = GetLength(leerdammer); for (var i = 0; i < len; ++i) { if(leerdammer[i] == nil) { ++move; continue; } leerdammer[i - move] = leerdammer[i]; } SetLength(leerdammer, len - move); // assert IsGouda(leerdammer) return move; } // Removes duplicate entries - returns the number of entries removed. global func RemoveDuplicates(array arr) { var working = []; var cnt = 0; var len = GetLength(arr); for (var i = 0; i < len; ++i) { if (IsValueInArray(working, arr[i])) { ++cnt; continue; } working[GetLength(working)] = arr[i]; } SetLength(arr, GetLength(working)); for (var i = GetLength(working); --i >= 0;) arr[i] = working[i]; return cnt; } // Tests whether a value is in an array. global func IsValueInArray(array arr, /*any*/ value) { return GetIndexOf(arr, value) != -1; } // Removes a value from an array. global func RemoveArrayValue(array arr, /*any*/ value, bool unstable) { var i = GetIndexOf(arr, value); if (i == -1) return false; if (unstable == true) return RemoveArrayIndexUnstable(arr, i); return RemoveArrayIndex(arr, i); } // Randomly shuffles an array. global func ShuffleArray(array arr) { var len = GetLength(arr); var working = arr[:]; while (--len >= 0) { var i = Random(len + 1); arr[len] = working[i]; working[i] = working[len]; } return; } // Takes array of format [[x1,y1], [x2,y2], ...] and returns array [[x1,x2,...],[y1,y2,...]] global func TransposeArray(array v) { var result = [], i = 0; for (var vc in v) { var j = 0; for (var c in vc) { if (!result[j]) result[j] = CreateArray(GetLength(v)); result[j][i] = c; ++j; } ++i; } return result; } // Deletes an index from an array, does not change the order of items in the array. global func RemoveArrayIndex(array arr, int index, bool unstable) { if (unstable == true) return RemoveArrayIndexUnstable(arr, index); // move all elements right of index to the left arr[index:] = arr[index+1:]; return true; } // Deletes an array item - might change the order of elements, but is faster. global func RemoveArrayIndexUnstable(array arr, int index) { arr[index] = arr[-1]; SetLength(arr, GetLength(arr) - 1); return true; } // Inserts an element at the end of an array. global func PushBack(array arr, /*any*/ value) { arr[GetLength(arr)] = value; return true; } // Inserts an element at the beginning of an array. global func PushFront(array arr, /*any*/ value) { // Move elements one to the right. arr[1:] = arr; arr[0] = value; return true; } // Removes the last element from an array and returns it. global func PopBack(array arr) { if (GetLength(arr) == 0) return nil; var o = arr[-1]; arr[:] = arr[:-1]; return o; } // Removes the first element from an array and returns it. global func PopFront(array arr) { if (GetLength(arr) == 0) return nil; var o = arr[0]; arr[:] = arr[1:]; return o; } // Returns a random element from an array. global func RandomElement(array arr) { return arr[Random(GetLength(arr))]; } // Move array of indexes before given element. Called from editor on item move. global func MoveArrayItems(array arr, array source_indices, int insert_before) { if (!arr) return false; var len = GetLength(arr), off = 0, val; // make sure source indices are sorted if (len > 1) { source_indices = source_indices[:]; SortArray(source_indices); } for (var idx in source_indices) { if (idx < 0) idx += (1-(idx+1)/len)*len; // resolve negative indices if (idx >= len) continue; if (idx < insert_before) { // Move element forward idx += off; --off; // Adjust for other elements already moved val = arr[idx]; while (++idx < insert_before) arr[idx-1] = arr[idx]; arr[insert_before - 1] = val; } else { // Move element backward val = arr[idx]; while (idx-- >= insert_before) arr[idx+1] = arr[idx]; arr[insert_before] = val; ++insert_before; } } return true; } // Deletes multiple indexes from an array, does not change the order of items in the array. global func RemoveArrayIndices(array arr, array indices) { indices = indices[:]; SortArray(indices, true); for (var idx in indices) if (idx < GetLength(arr)) RemoveArrayIndex(arr, idx); return true; } // Performs a left fold. // // Examples: // - Reduce([1, 2, 3, 4], Min) == 1 // - func Add(int a, int b) { return a + b; } // Reduce([1, 2, 3, 4], Add, 100) == 110 global func Reduce(array arr, func fn, initial) { var i = 0; var result = initial ?? arr[i++]; while (i < GetLength(arr)) result = Call(fn, result, arr[i++]); return result; }