AS3 Finding common values in Arrays - arrays

I'm struggling with something that shouldn't be too difficult but I can't figure it out I have a number of Arrays with different values and I want to find the common values all of the Arrays have, see example below:
var arrayOne:Array = ["1","2","3"];
var arrayTwo:Array = ["1","2","7"];
var arrayThree:Array = ["1","2","9","12"];
_resultArray = ["1","2"];
Any help is appreciated.

You can do something like:
///Returns common values between to arrays
function getCommonValues(array1:Array, array2:Array):Array
{
var len1:int = array1.length;
var len2:int = array2.length;
var toReturn:Array = new Array();
for(var i:int = 0; i < len1; i++){
for(var n:int = 0; n < len2; n++){
if(array1[i] == array2[n]){
toReturn.push(array1[i]);
}
}
}
return toReturn;
}
Then do something like:
var arrayOneAndTwo:Array = getCommonValues(arrayOne,arrayTwo);
var _resultArray:Array = getCommonValues(arrayOneAndTwo,arrayThree);
Optionally you can modify the function to include all three arrays in the comparison, which would be more efficient.
Edit
If you want to process an unknown amount of arrays you can add:
///Returns common values between X number of sub arrays
function getCommonValuesFromSubArrays(papaArray:Array):Array
{
if(papaArray.length < 2){ return papaArray; }
var toReturn:Array = papaArray[0];
for(var a:int = 1; a < papaArray.length; a++){
toReturn = getCommonValues(toReturn, papaArray[a]);
}
return toReturn;
}
Then something like:
var arr1:Array = ["one","two","three","four","five"];
var arr2:Array = ["one","two","five","six"];
var arr3:Array = ["one","two","three","four","five"];
var arr4:Array = ["one","two","three","four","five"];
var bigOlArray:Array = [arr1,arr2,arr3,arr4];
var _results:Array = getCommonValuesFromSubArrays(bigOlArray);

I would use a function to concatenate all arrays, sort by numerical value, and collect all items that are available exactly as many times as the number of arrays that were passed in as parameters:
var arrayOne : Array = [ "1", "2", "3" ];
var arrayTwo : Array = [ "1", "2", "7" ];
var arrayThree : Array = [ "1", "2", "9", "12" ];
// you can pass in any number of Arrays
trace ( searchArraysForCommonItems ( arrayOne, arrayTwo, arrayThree ) ); // returns ["1", "2"]
function searchArraysForCommonItems ( ...args : * ) : Array
{
var searchArray : Array = [];
for each ( var arr:Array in args)
searchArray = searchArray.concat ( arr );
var resultArray : Array = [];
var last : String;
var times : int = 0;
for each ( var str : String in searchArray.sort ( Array.NUMERIC ))
if (last == str) times++;
else
{
if (times == args.length) resultArray.push ( last );
last = str;
times = 1;
}
return resultArray;
}
Of course, you can (and should) use Vector.<String> instead of Array wherever possible to improve performance, but always remember that Array.sort() is a native function and very fast...

I would use the Array.filter() Function to achieve this:
var _resultArray:Array = arrayOne.filter(
function(item:String, index:int, arr:Array):Boolean
{
return (arrayTwo.indexOf(item) != -1 && arrayThree.indexOf(item));
}
);
This will loop over arrayOne and return an array with the values that both appear also in arrayTwo and arrayThree.
Edit: And here is a function that will take any number of arrays and return the common values:
function getCommonValues(arrayOne:Array, ... arrays:Array):Array
{
var _resultArray:Array = arrayOne.filter(
function(item:String, index:int, arr:Array):Boolean
{
return arrays.every(
function (a:Array, index2:int, arr2:Array):Boolean
{
return a.indexOf(item) != -1;
}
);
}
);
return _resultArray;
}
Usage:
resultArray = getCommonValues(arrayOne, arrayTwo, arrayThree, arrayFour);
The function has another nested closure inside the first one, so might be a bit hard to understand, but I tested it, it works.

Related

loop to create array of arrays of same-length strings

I'm trying to create an array of arrays that are grouped according to their lengths (strings), such that the array below:
var testA = ["carts","carts","cars","cars","ca","ca", "ca","a","a","a","a"];
would become:
var sortedArrays = [["carts","carts"], ["cars","cars"],["ca","ca","ca"], ["a","a","a","a"]]
I am currently trying the loop below but simply cannot get this to work. I know it'll be something simple, but I've spent so long trying to complete this with no that it's proving incredibly frustrating.
var testA = ["carts","carts","cars","cars","ca","ca", "ca","a","a","a","a"];
var sortedArrays = [];
for(i=0; i < testA.length; i++){
longestWord = 0;
wordHolder = []
wordHolder.push(testA[i])
if (testA[i].length > longestWord){
longestWord = testA[i].length
wordHolder.push(testA[i])
}
sortedArrays.push(wordHolder)
}
Any help will be greatly appreciated
What about the following code (Swift, but it should be easy to reformulate it in other languages):
let testA = ["carts","carts","cars","cars","ca","ca", "ca","a","a","a","a"]
var maxLength = 0
for string in testA {
if string.count > maxLength { maxLength = string.count }
}
var sortedArrays: [[String]] = []
for nextLength in 0 ... maxLength {
let invertedLength = maxLength - nextLength
let nextArray = testA.filter { $0.count == invertedLength }
sortedArrays.append(nextArray)
}
This code creates also empty arrays, which can of course easily be skipped.
The question, of course, is what your requirements are. The code above is compact, but it is not fast for large arrays...
For large arrays, it would be better, first to sort testA, and then to extract the elements.
Sticking with java script, I was able to do the following. My assumption is the words are already sorted descending by length and that there is only one word of each length. That's based on what you were doing. I think what was going on is that too much was getting initialized or reset each time through the loop.
var testA = ["carts", "carts", "cars", "cars", "ca", "ca", "ca", "a", "a", "a", "a"];
var sortedArrays = [];
var wordHolder = []; // took outside loop to ensure initialized
var curLength = testA[0].length;// assuming here that testA not empty
for (var i = 0; i < testA.length; i++) {
if (testA[i].length === curLength) { // more of the same
wordHolder.push(testA[i]);
} else { // new block starts
curLength = testA[i].length;
sortedArrays.push(wordHolder);
// alert (wordHolder)
// alert (sortedArrays)
wordHolder = [];
wordHolder.push(testA[i]);
}
}
sortedArrays.push(wordHolder);// add the last one

Search and use of Strings in 2D Arrays

I got a 2D array where I want to fetch data from the 2nd dimension based on the 1st, but I dont understand how to set it up in Swift 2 since the old for-loop function is deprecated.
Based on the name (Burt) I want to present the phone-No and Group.
myArray: [[String]] = [["Adam", "123456", "Group1"], ["Burt", "251436", "Group2"], ["Cesar", "918273", "Group3"], ["David", "552277", "Group4"]
For i in 0..myArray.count {
If myArray[i][0] == "Burt" {
phoneNoLabel.text = myArray[i][1]
  GroupNoLabel.text = myArray[i][2]
}
}
This is how I solved it with the help of Tarun Seera.
let myArray = [["Adam", "123456", "Group1"], ["Burt", "251436", "Group2"], ["Cesar", "918273", "Group3"], ["David", "552277", "Group4"]]
var user: String = "Burt"
var phoneNo: String = ""
var groupNo: String = ""
for i in myArray {
if i[0] == user {
phoneNo = i[1]
groupNo = i[2]
}
}
You can also make entities (NSObject)array and use predicate to achieve the same thing and still if you want this form 2d array you can use below code
let myArray = [["Adam", "123456", "Group1"], ["Burt", "251436", "Group2"], ["Cesar", "918273", "Group3"], ["David", "552277", "Group4"]]
for i in myArray {
if i[0] == "Burt" {
print("Hurrey I am in.. my name is: \(i[0]) my Id is:\(i[1]) and my gourp is:\(i[2])")
}
}
for i in 0..<myArray.count {
if myArray[i][0] == "Burt" {
phoneNoLabel.text = myArray[i][1]
GroupNoLabel.text = myArray[i][2]
}
}
Use
..<
instead of just
..
Your problem is, that i is going from 0 to myArray.count - which is 4 .. that means your i is going 0,1,2,3,4 = you have 5 times i. Your array only has 4 "items".
for i in 1...myArray.count{
if myArray[i-1][0] == "Burt" {
phoneNoLabel.text = myArray[i-1][1]
GroupNoLabel.text = myArray[i-1][2]
}
}
or
for i in 0...myArray.count-1{
if myArray[i][0] == "Burt" {
phoneNoLabel.text = myArray[i][1]
GroupNoLabel.text = myArray[i][2]
}
}
should solve your problem.
As an alternative to explicit looping, you could use a functional programming approach
let searchForUser = "Burt"
let userInfo = Array(myArray
.flatMap{ $0.first == searchForUser ? $0.suffixFrom(1) : nil }
.flatten())
print(userInfo) // ["251436", "Group2"]
For you specific example, the user info you're after is readily obtainable from the userInfo array
phoneNoLabel.text = userInfo[0] // 251436
groupNoLabel.text = userInfo[1] // Group2
Note here that I've renamed GroupNoLabel variable (UILabel?) from the example in your question to groupNoLabel, as variables in Swift should, by convention, use camelCase names (and not CamelCase, as is used e.g. for types).

outside array not affected from function appending within

I am working with arrays and I created a function that appends an array from within. However when I print the array, it still appears empty. What gives?
var queriesFinal : [String] = []
func queryValidator(search : String)
{
var letterSet = NSCharacterSet(charactersInString: "abcdefgjhijklmnopqrstuvwxyz ")
var numberSet = NSCharacterSet(charactersInString: "1234567890".uppercaseString)
var queriesTwo : [String] = search.lowercaseString.componentsSeparatedByCharactersInSet(letterSet)
for(var x = 0; x < queriesTwo.count; x++)
{
for(var y = 0; y < 10; y++)
{
var str = String(y)
if(queriesTwo[x] == str)
{
var numberStr = String(queriesTwo[x]) + "th"
queriesFinal.append(numberStr)
}
}
}
}
println(queriesFinal)
search = "Matt 8th"
queryValidator(search)
This code can run in playground..
I appreciate any help!
As mentioned by Mike S, you've made a small mistake println should be after your queryValidator, I've also added an optional in case your queryValidator search returns nil, also as mentioned by Zaph you don't need numberSet, so I removed it:
func queryValidator(search : String) -> [String]? {
let queriesTwo:[String] = search.lowercaseString.componentsSeparatedByCharactersInSet(NSCharacterSet(charactersInString: "abcdefgjhijklmnopqrstuvwxyz "))
var queriesResult:[String] = []
for x in 0...queriesTwo.count-1 {
for y in 0...9 {
if(queriesTwo[x] == String(y)) {
queriesResult.append(String(queriesTwo[x]) + "th")
}
}
}
return queriesResult.count > 0 ? queriesResult : nil
}
var search = "Matt 8 less7"
if let queriesFinal = queryValidator(search) {
println(queriesFinal)
} else {
println("no result")
}
An alternative approach with Regular Expressions:
func queryValidator(search: String) -> [String] {
var queriesFinal:[String] = []
var nsSearch: NSString = search
let pattern = "(\\d+)"
var regEx = NSRegularExpression(pattern:pattern, options:nil, error:nil)
regEx?.enumerateMatchesInString(nsSearch, options:nil, range:NSMakeRange(0, nsSearch.length), usingBlock: { (result, flags, stop) in
let found = nsSearch.substringWithRange(result.range)
queriesFinal.append("\(found)th")
})
return queriesFinal
}
var result = queryValidator(search)
println("result: \(result)")
Output:
result: [8th, 7th, 6th]
For information on regular expressions see: Regular Expressions

as3 comparing two arrays and returning index

i want to create a function that compares 2 arrays and returns indexes of items found. if for examples my arrays are:
var distances:Array = new Array (0,275,217,385,275,0,251);
var selectedDist:Array = new Array (217,275,251);
i would like it to return 2,4,6
Try the following:
var indices:Array = [];
for each(var distance:int in selectedDist) {
var index:int = distances.indexOf(distance);
if (index >= 0) {
indices.push(index);
}
}
return indices;
Supposing you would always compare selectedDist array to distances array, I would do that :
protected function compareArrays(arr1:Array, arr2:Array):Array
{
var matches:Array = new Array();
for(var x:int=0; x < arr2.length; x++) {
/*
* indexOf returns -1 id the element is not found in the array
* http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/Array.html#indexOf()
* but you have to grab the lastIndexOf 275, as requested...
*/
if (arr1.indexOf(arr2[x] > -1))
matches.push(arr1.lastIndexOf(arr2[x]));
}
return matches;
}

Flex 3 Actionscript Array Subtract function

Can anyone tell me how to compare two arrays and delete the common terms in ActionScript?
Eg:
Array1 = [2,4,6,8,10,12]
Array2 = [1,2,3,4,5,6,7,8,9,10,11]
Array1 - Array2 = [12]
If you use ActionLinq, it is very easy to do set mathematics like this:
var array1:Array = [2,4,6,8,10,12];
var array2:Array = [1,2,3,4,5,6,7,8,9,10,11];
var subtraction:Array = Enumerable.from(array1)
.except(Enumerable.from(array2))
.toArray();
You can filter using a custom function.
This is not an optimized way of filtering a difference of arrays, but it'll get the job done.
subtraction = Array1.filter(function(item:*, index:int, arr:Array){
var i:int;
var l:int;
l = Array2.length;
for ( i=0; i < l; i++ )
{
if ( Array2[i] == item )
{
return false;
}
}
return true;
});
If you wish to knock out all duplicates from an Array then I suggest that you use a Set to make the lookup speed as fast as possible:
const a : Array = [ 2, 3, 4 ];
const b : Array = [ 3, 4, 5 ];
// Create a Set for Array 'b' to provide a fast lookup table.
const setB : Object = {};
var prop : *;
for each (prop in b) {
setB[key] = true
};
// Find all values which only belong in Array 'a'.
const uniqueToA : Array = [];
for each (prop in a) {
if (setB[prop] === undefined) {
uniqueToA.push(prop);
}
}
If you find yourself doing a lot of work with collections then I would advise you invest in a Collections Framework such as AS3Commons Collections.

Resources