How do I look for bool values in array? - arrays

I have an array of objects, each containing a bool value with yes or no. I want to copy all objects with bool YES to another array. How can i do that? i have considered filtering the array using a predicate or integrating it in a for-loop, but i cant seem to get it right.
I need something like this:
for (BOOL* opslag_Set in [dataSource allKeys]){
NSArray *array = [dataSource objectForKey:opslag_Set];
for (int j = 0; j < [array count]; j++) {
if ([[array objectAtIndex:j] isEqualToString:#"YES"]) {
add object to another array;
}
}
}
First object of my array:
},
{
Dato = "2012-11-07 16:20:57 +0000";
Forfatter = "Vej 51, st. tv.";
Indhold = "Referat af beboerm\U00f8de";
"Opslag_set" = 0;
Overskrift = "Beboerm\U00f8de";
Prioritet = 0;
Svar = (
{
Dato = "2012-11-07 16:23:07 +0000";
Forfatter = "6. tv.";
Indhold = "Fedt fedt fedt";
}
);
},

You will have to use NSNumber in order to store the bools in an array.
Assuming your boolean array is called boolArray, the code to get an array with only YES would be something like this:
NSMutableArray* temp = [NSMutableArray new];
for (NSNumber* value in boolArray)
{
if ([value boolValue])
{
[temp addObject:[NSNumber numberWithBool:YES]];
}
}
However, why are you trying to do this? This will return an array with a certain number of elements that are all the same. You could just count the number if that's what you want. The other thing I can think of is that you have an object with a bool property, in which case you can easily adapt the code above.
EDIT: OK, let's assume that we have an object called MyDataObject that has a bool property - NSNumber* boolProperty. Here is the code:
NSMutableArray* temp = [NSMutableArray new];
for (MyDataObject* value in boolArray)
{
if ([value.boolProperty boolValue])
{
[temp addObject:value];
}
}
This should work for what you are doing. temp will reference the original objects - they are not being copied.

Related

Deleting Elements in Array equal to a value

I'm trying to make a code that removes all the elements from the array that are equal to a given value. For example an array = [hi, hello, hi, bye] value = hi, it would given an output hello bye
Here's my code:
int count = 0;
for(int i=0; i<stringArr.length;
if(stringArr[i].equals(value)){
count--;
for(int j= i; j<stringArr.length-1; j++){
stringArr[j] = stringArr[j+1];
}
i--;
}
}
Problem is instead of the expected output as: hello bye
It gives an output of:
hello hi bye bye
Try Java stream api:
String value = "hi";
String[] stringArr = new String[] {"hi", "hello", "hi", "bye"};
String[] results = Arrays.stream(stringArr)
.filter(it -> !it.equalsIgnoreCase(value))
.toArray(String[]::new);
The problem is that you are shifting the values left but not decrementing the length of the array in the outer for.
Assign stringArr.length to count and use it in the for.
Trading memory for speed, you could create a new array of the same length and only add in the first occurrence of what you want.
String[] removeEqual(String[]array,String val){
boolean found =false;
String[]out=new String[array.length];
int count=0;
for (int i=0;i<array.length;i++){
if(array[i].equals(val)){
if(!found){
out[count++]=val;
found=true;
}
else out[count++]=val;
}
}
return Arrays.copyOf(out, count);
}
You may like to consider separate functions for separate conditions such as removeLessThan and removeGreaterThan to keep it functionally coherent.
I don't recommend to do any manipulation to the original array, create a new one. Recycling is good for the planet, but may be very harmful in code. So if you want to stick to the Arrays only, then create a new array with and add all elements you want into the new array, but I think you can do better. Your approach is very "C" like, this is Java, you have a lot of better tools, than arrays.
One of them are streams and lambdas like this
#Test
public void example_lambdas() {
String[] array = {"hi", "hello", "hi", "bye"};
String[] result = Arrays.stream(array).filter(element -> !"hi".equals(element)).toArray(String[]::new);
System.out.println(Arrays.toString(result));
}
Another option is to use list
#Test
public void example_list() {
String[] array = {"hi", "hello", "hi", "bye"};
List<String> list = new ArrayList<>(Arrays.asList(array));
Set<String> toBeRemoved = Collections.singleton("hi");
list.removeAll(toBeRemoved);
String[] result = list.toArray(new String[0]);
System.out.println(Arrays.toString(result));
}
An array has a fixed size that cannot be changed. Hence your result cannot be a two element array when you start with a four element array. If you want the result to be a two element array, then you will need to create a second array. If, however, you want the result to stay in the original array, then I suggest setting the excess array elements to null. The following code demonstrates.
String[] stringArr = {"hi", "hello", "hi", "bye"};
String condition = "==";
String value = "hi";
int count = stringArr.length;
for (int i = 0; i < count; i++) {
if (condition.equals("==")) {
if (stringArr[i].equals(value)) {
count--;
for (int j = i; j < stringArr.length - 1; j++) {
stringArr[j] = stringArr[j + 1];
}
stringArr[stringArr.length - 1] = null;
}
}
}
System.out.println(java.util.Arrays.toString(stringArr));
The above code prints the following:
[hello, bye, null, null]
EDIT
As requested, below code creates a new array that only contains the requested elements, i.e. the ones that were not removed from the original array.
String[] stringArr = {"hi", "hello", "hi", "bye"};
String condition = "==";
String value = "hi";
String[] temp = new String[stringArr.length];
int count = 0;
for (int i = 0; i < stringArr.length; i++) {
if (condition.equals("==")) {
if (!stringArr[i].equals(value)) {
temp[count++] = stringArr[i];
}
}
}
String[] result = new String[count];
for (int i = 0; i < count; i++) {
result[i] = temp[i];
}
System.out.println(Arrays.toString(result));
The above code prints the following:
[hello, bye]
In other words, result is a two element array.
Note that I assume that you only want to do array manipulation and you don't want to use classes in the JDK that most of the other answers have used.

sorting strings in an array alphabetically

I came up with this code to try and sort out an array of strings (I don't want to use ints or imports as I'm trying to understand iteration loops), but it only rearranges the first two strings. Can anyone point out my mistakes?
public class Alpha8 {
public static void main(String[] args) {
String[] Names = {"O","B","K","S","D","M","N","A"};
String temp = null;
for(int i=0;i<Names.length;i++){
for(int j = i+1;j<Names.length;j++) {
if(Names[j].compareTo(Names[i])<0)
temp = Names[i];
Names[i] = Names[j];
Names[j] = temp;
for( i = 0;i<Names.length;i++){
System.out.println(Names[i]);
}
}
}
}
}
You have made two mistakes:
You are printing the array inside your 'swap' code. You should only print the array once the sorting is complete.
You only iterate through the array once. For a bubble sort (which is what you are implementing) you need to keep iterating through until no swaps occur.
The method should look something like:
boolean hasSwapped;
do {
hasSwapped = false;
for (int i = 1; i < names.size(); i++) {
if (names[i-1].compareTo(names[i]) > 0) {
swap(names[i-1], names[i]);
hasSwapped = true;
}
}
} while (hasSwapped);

Iterating through objects with numbered names

I'm actually trying to figured out how i can iterate through some objects in a for loop with names like "Object1, Object2, Object3..."
Here is a code to exemplify what i'm trying to do:
for(int i = 0; i <= numberOfObjects; i++) {
someVariable = Object1.value/Object2.value/Object3.value;
}
In this case in the part of the code that i have the Object1,Object2 and Object3 i will change for something, example Object[i].
In this case it can't be done with arrays since i don't know how much objects were created.
For the C++ language
Put the objects into a std::vector.
Your loop will look like:
for (unsigned int i = 0; i < object_vector.size(); ++i)
{
result = result / object_vector[i].value;
}
For the C language
object my_objects[] = {object1, object2, /*...*/};
array_size = sizeof(my_objects) / sizeof(object);
for (unsigned int i = 0; i < array_size; ++i)
{
result = result / my_objects[i].value;
}
Use an array:
std::vector<T> objects{Object1, Object2, Object3};
for (auto&& x : objects) {
someVariable = x.value;
}
There's no other way to do it.

as3 random array - randomize array - actionscript 3

How do you randomize an array using actionscript 3?
There is a short version using Array.sort() function:
var arr : Array = [0,1,2,3,4,5,6,7,8,9];
function randomize ( a : *, b : * ) : int {
return ( Math.random() > .5 ) ? 1 : -1;
}
trace( arr.sort( randomize ) );
If you don't get "enough" randomness you can sort twice :)
EDIT - explanation line by line:
For Array class method sort() you can pass not only sort options like Array.CASEINSENSITIVE, Array.DESCENDING and so on but also your own custom compare function reference (a callback) that accepts two parameters (two elements from array to compare). From AS3 documentation:
A comparison function should take two arguments to compare. Given the elements A and B, the result of compareFunction can have a negative, 0, or positive value:
A negative return value specifies that A appears before B in the sorted sequence.
A return value of 0 specifies that A and B have the same sort order.
A positive return value specifies that A appears after B in the sorted sequence.
Note: compare function parameters might be typed (if your array is typed) and have any name you want eg.:
function compareElements ( elementA : SomeClass, elementB : SomeClass ) : int;
This method is very useful when you need to sort array elements by their special properties. In randomization case compareFunction randomly returns -1, 0 or 1 and makes array elements to switch their places (indices). I have found that better randomization (in my subjective and mathematically untested opinion) is when method returns only -1 and 1. Also have in mind that sorting function with custom compare function doesn't compare elements sequentially so in some special cases randomization results may differ from what you might expect.
There's a better way that will also allow you to randomize the array in place, if you need that, and it will not make you create more then a single copy of your original array.
package
{
import flash.display.Sprite;
public class RandomizeArrayExample extends Sprite
{
public function RandomizeArrayExample()
{
super();
testDistribution();
}
private function testDistribution():void
{
var hash:Object = { };
var tester:Array = [1, 2, 3, 4];
var key:String;
for (var i:int; i < 1e5; i++)
{
randomize(tester);
key = tester.join("");
if (key in hash) hash[key]++;
else hash[key] = 1;
}
for (var p:String in hash) trace(p, "=>", hash[p]);
}
private function randomize(array:Array):Array
{
var temp:Object;
var tempOffset:int;
for (var i:int = array.length - 1; i >= 0; i--)
{
tempOffset = Math.random() * i;
temp = array[i];
array[i] = array[tempOffset];
array[tempOffset] = temp;
}
return array;
}
}
}
I had an alternative requirement where i wanted to randomly insert lots of source arrays into a target array randomly. Like Rytis i'm a big fan of the forEach, map and sort functions on Arrays.
var randomInsert:Function = function callback(item:*, index:int, array:Vector.<MyItem>):void
{
var j:Number = Math.floor(Math.random() * targetArray.length);
targetArray.splice(j,0,item);
}
targetArray = new Vector.<MyItem>();
sourceArray1.forEach(randomInsert, this);
sourceArray2.forEach(randomInsert, this);
here's an easier function. Works also on multidimensional arrays
function randomizeArray(array:Array):Array
{
var newArray:Array = new Array();
while (array.length > 0)
{
var mn=Math.floor(Math.random()*array.length)
newArray[newArray.length]=array[mn]
array.splice(mn,1)
}
return newArray;
}
I found this very helpful. I hope it can help you too.
// Array to Randomize
var firstArray:Array = ["One","Two","Three","Four","Five","six","seven","eight","nine","ten"];
trace(firstArray); // Prints in order
var newArray:Array = new Array();
function randomizeArray(array:Array):Array
{
var newArray:Array = new Array();
while (array.length > 0)
{
newArray.push(array.splice(Math.floor(Math.random()*array.length), 1));
}
return newArray;
}
var randomArray:Array = randomizeArray(firstArray);
trace(randomArray); // Prints out randomized :)
If you need your array to be shuffled (your elements can not repeat). You could use this function:
/**
* Shuffles array into new array with no repeating elements. Simple swap algorithm is used.
*/
public function shuffleArray(original:Array):Array
{
// How many swaps we will do
// Increase this number for better results (more shuffled array, but slower performance)
const runs:int = original.length * 3;
var shuffled:Array = new Array(original.length);
var i:int;
var a:int;
var b:int;
var temp:Object;
// Copy original array to shuffled
for(i=0; i<shuffled.length; i++){
shuffled[i] = original[i];
}
// Run random swap cycle 'runs' times
for(i=0; i<runs; i++){
// There is a chance that array element will swap with itself,
// and there is always small probability it will make your shuffle
// results not that good, hence try to experiment with
// different runs count as stated above
a = Math.floor(Math.random() * original.length);
b = Math.floor(Math.random() * original.length);
// Swap messages
temp = shuffled[a];
shuffled[a] = shuffled[b];
shuffled[b] = temp;
}
return shuffled;
}
Usage:
var testArray:Array = ["Water", "Fire", "Air", "Earth"];
trace(shuffleArray(testArray).concat());
this is how I randomize my array of 36 cards for a memory game
const QUANT_CARTAS: int = 36;
//get the 36 numbers into the array
for (var i: int = 0; i < QUANT_CARTAS; i++)
{
cartas.push(i);
}
//shuffles them =)
for (var moeda: int = QUANT_CARTAS - 1; moeda > 0; moeda--)
{
var pos: int = Math.floor(Math.random() * moeda);
var carta: int = cartas[moeda];
cartas[moeda] = cartas[pos];
cartas[pos] = carta;
}
// and add them using the random order...
for (i = 0; i < QUANT_CARTAS; i++)
{
var novaCarta: Carta = new Carta();
novaCarta.tipoCarta = cartas[i];
etcetcetc.............
}
choose random string from array
function keyGenerator(len:Number):String
{
function randomRange(minNum:Number, maxNum:Number):Number
{
return (Math.floor(Math.random() * (maxNum - minNum + 1)) + minNum);
}
var hexArray = ['0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'];
var key = "";
for (var i=0; i<len; i++)
{
key += hexArray[randomRange(0,hexArray.length-1)];
}
return key;
}
usage:
trace(keyGenerator(16));

AS3: Refer to different arrays dynamically?

This might be a simple one, and if it is I'm sure I'll feel stupid.
Basically, I have arrays a1, a2 and a3.
Using a for statement..
for (var i 0; i < 4; i++) {
//stuff
}
How can I push data in the for statement into one of these arrays using i? That is, each time adding the data into the next group up. a[0] -> a[1] etc. I tried getDefinitionByName but it seems that only works for library objects!
Sorry if it's simple!
Cheers in advance.
EDIT:
The code in full where I need this to work. This is what I tried using the first answer I was given.
var fullList:Vector.<Array> = new Vector.<Array>();
for (var i1 = 0; i1 < 3; i1++)
{
fullList.push(new Array());
}
var levelLoader:URLLoader = new URLLoader();
levelLoader.addEventListener(Event.COMPLETE, levelLoaded);
function levelLoaded(e:Event):void
{
var indexcount = 0;
txttileArray = e.target.data.split("a");
txtDebug.text = txttileArray.toString();
for (var i = 1; i < 4; i++)
{
temparray1 = txttileArray[indexcount].split("");
for (var row = 0; row < temparray1.length; row ++)
{
var a = getDefinitionByName(temparray1[row] + "Tile") as Class;
//trace(a);
var b = new a ;
b.x = 17 + 17 * row;
b.y = 17 + 17 * indexcount;
addChild(b);
fullList[indexcount].push(b);
}
indexcount++;
}
}
sorry for the messy variable names.
i have three arrays, a1, a2 and a3. i want to be able access these
arrays based on the value of the variable "i". so for example, if "i"
is 1, i want to push a data value to a1. and so on – hazdog
This is not possible if you have arrays a1, a2 and a3 as local (defined in the function) variables. If they are defined in the class, then here's how you do it:
private var a1:Array=[];
private var a2:Array=[];
private var a3:Array=[];
private function pushValue(identifier:String, value:Object):int {
var name:String="a" + identifier;
var target:Array=this[name] as Array;
if(target == null) {
throw new Error("No such array " + name);
} else {
return target.push(value);
}
}
//And then call it like this:
pushValue("1", "This value goes in array a1");
pushValue("1", "This is another value that goes in array a1");
pushValue("2", "This value goes in array a1");
pushValue("2", "This is another value that goes in array a2");
pushValue("3", "This value goes in array a3");
pushValue("3", "This is another value that goes in array a3");
Otherwise, you can define an array of arrays (or vector of arrays), say holderArray in which you put your target arrays, and then push the value to holderArray[identifier]
EDIT
Instead of defining a1, a2 and a3 in the this object, define it like this:
private var arrayHolder:Object={};
private function init():void {
for(var i:int=1; i<=3; i++) {
arrayHolder["a" + i]=new Array();
}
}
init();
Then, your arrays will be stored as arrayHolder.a1, arrayHolder.a2, arrayHolder.a3 etc
And modify pushValue as follows:
Change
var target:Array=this[name] as Array;
to
var target:Array=arrayHolder[name] as Array;
Inception.
You need to use Array in Array.
private var fullList:Vector.<Array>;
private var total:uint = 4;
function a():void
{
// first creating array list
fullList = new Vector.<Array>();
for (var i:uint = 0; i < total; i++)
{
fullList.push(new Array());
}
}
function b():void
{
// doing the stuff
for (var i:uint = 0; i < total; i++)
{
switch (i)
{
case 0:
fullList[i].push('zero-array-push');
break;
case 1:
fullList[i].push('one-array-push');
break;
case 2:
fullList[i].push('two-array-push');
break;
case 3:
fullList[i].push('three-array-push');
break;
}
}
}

Resources