How to sort a NSMutableArray with custom object? - nsmutablearray

i have a mutable array with objects "XX" and i want to sort the array according to the variables contained in the object "XX" (see below the structure of the object).
I want to sort the array ascending by VALUE1,VALUE2 and then by NAME.
Is there any way to do it?
#interface XX:NSObject{
float VALUE1;
float VALUE2
NSString* NAME;
}
#end interface
Any help , very much appreciated!!! :-)
Thank you!

What you need to use is something called a Comparator block. This can be used to sort your array when you do
array sortUsingComparator: ^(id objA, id obj2){
if(((XX*)objA).Value1 > ((XX*)obj2).Value1){
return (NSComparisonResult)NSOrderedDescending;
}else if(((XX*)objA).Value1 < ((XX*)obj2).Value1){
return (NSComparisionResult)NSOrderedAscending;
}else{
//keep comparing here, because value 1 are equal
}
//sorting logic goes here, returning a (NSComparisonResult) type here
}];

Related

groovy map usage difficulty in creating (slightly) complex data structures

I'm trying to query a database and store the results in a Groovy map data structure with some nested data elements and can't seem to figure it out.
Here's my latest attempt -
#!/usr/bin/env groovy
import groovy.sql.Sql;
// code to connect to database omitted
TreeMap tsMap = [:];
def tabcount = 0, inxcount = 0;
dbconn.eachRow("SELECT table_name,tablespace_name FROM user_tables") {
tabcount += 1;
if (tsMap.containsKey(it.tablespace_name)) {
tsMap[it.tablespace_name].tabs++;
} else {
type = [tabs:1];
tsMap[it.tablespace_name] = type;
}
}
dbconn.eachRow("SELECT index_name,tablespace_name FROM user_indexes") {
inxcount += 1;
if (tsMap.containsKey(it.tablespace_name) {
tsMap[it.tablespace_name].inxs++;
} else {
type = [inxs:1];
tsMap[it.tablespace_name] = type;
}
}
tsMap.eachWithIndex { entry, i ->
printf("%3d - Tablespace: %-30s contains %4d tables and %4d indexes\n",
i, entry.key, entry.value.tabs, entry.value.inxs);
}
printf("Total table count = %d\n", tabcount);
printf("Total index count = %d\n", inxcount);
And here's what I want tsMap to end up with -
tsMap = [TS1:[tabs:10], TS2:[tabs:35, inxs:12]]
The TS1 entry (where there are only "table" entries and no "index" entries) works but as soon as there are also index entries I end up with -
tsMap = [TS1:[tabs:10], TS2:[inxs:12]]
even though TS2 also has 35 tables in addition to the 12 indexes.
My goal is to get tsMap to look like -
tsMap = [TS1:[tabs:10], TS2:[tabs:35, inxs:12]]
I use associative arrays in other languages and run into similar challenges anytime attempting to store arrays (of any kind) in them to create complex data structures. With Groovy's Java underpinning I expected it to be easy and straightforward but if so then I'm missing something.
I'm already not happy with the complexity of this code as is and would appreciate pointers on how to simplify it. I expected this to be very simple and straightforward, even trivial, and I took a wrong turn somewhere and it's anything but simple at this point.
Obviously I could just have two maps and end up with -
tabMap = [TS1:10, TS2:35]
inxMap = [TS2:12]
but of course this is also an exercise in understanding how to go beyond simple associative arrays (maps) so any help would be appreciated as I'm working on my Groovy skills.
So based on #cfrick's feedback I've tried this, much more streamlined code -
TreeMap tsMap = [:].withDefault{ [tabs:0, inxs:0] };
def tabcount = 0, inxcount = 0;
workconn.eachRow("SELECT table_name,tablespace_name FROM user_tables") {
tsMap[it.tablespace_name].tabs++;
}
workconn.eachRow("SELECT index_name,tablespace_name FROM user_indexes") {
tsMap[it.tablespace_name].inxs++;
}
which really seemed to make sense and I thought it was going to do it but I end up with -
Caught: java.lang.NullPointerException: Cannot get property 'tabs' on null object
java.lang.NullPointerException: Cannot get property 'tabs' on null object
which previously I've learned is because Groovy can't find that nested map with the "tabs" key to be able to increment it.
I thought the .withDefault was going to add my nested map to any "key" that I added to the tsMap.
Any advice on where I've gone wrong is appreciated.
SOLUTION
OK, with #cfrick's help the objective is now working and here's the final code:
#!/usr/bin/env groovy
import groovy.sql.Sql;
// code to connect to database omitted
// avoid types other than def as they cast away the .withDefault
def tsMap = [:].withDefault{ [tabs:0, inxs:0] };
workconn.eachRow("SELECT table_name,NVL(tablespace_name, '(null)') tsName FROM user_tables") {
tsMap[it.tsName].tabs++;
}
workconn.eachRow("SELECT index_name,NVL(tablespace_name, '(null)') tsName FROM user_indexes") {
tsMap[it.tsName].inxs++;
}
def fmt = (opt.geninput) ? "%d,%s,%d,%d,%s\n" : "%3d - Tablespace: %-25s contains %4d tables and %4d indexes %s\n";
tsMap = tsMap.sort(); // sort the keys
tsMap.eachWithIndex { entry, i ->
printf(fmt, i, entry.key, entry.value.tabs, entry.value.inxs, (entry.value.tabs * entry.value.inxs != 0) ? "**" : "");
}
printf("Total table count = %d\n", tsMap.values()*.tabs.sum());
printf("Total index count = %d\n", tsMap.values()*.inxs.sum());
Thanks!

Threadsafe mutable collection with fast elements removal and random get

I need a thread safe data structure with three operations: remove, getRandom, reset.
I have only two ideas by now.
First: Seq in syncronized var.
val all: Array[String] = ... //all possible.
var current: Array[String] = Array.empty[String]
def getRandom(): = {
val currentAvailable = current
currentAvailable(Random.nextInt(currentAvailable.length))
}
def remove(s: String) = {
this.syncronized {
current = current diff Seq(s)
}
}
def reset(s: String) = {
this.syncronized {
current = all
}
}
Second:
Maintain some Map[String,Boolean], there bool is true when element currently is present. The main problem is to make a fast getRandom method (not something like O(n) in worst case).
Is there a better way(s) to implement this?
Scala's Trie is a lock free data structure that supports snapshots (aka your currentAvailable) and fast removals
Since I'm not a Scala expert so this answer is general as an example I used Java coding.
in short the answer is YES.
if you use a map such as :
Map<Integer,String> map=new HashMap<Integer,String>(); //is used to get random in constant time
Map<String,Integer> map1=new HashMap<String,Integer>(); //is used to remove in constant time
to store date,
the main idea is to keep the key( in this case the integer) synchronized to be {1 ... size of map}
for example to fill this structure, you need something like this:
int counter=0; //this is a global variable
for(/* all your string (s) in all */ ){
map.put(counter++, s);
}
//then , if you want the removal to be in constant time you need to fill the second map
for(Entry e : map.EntrySet(){
map1.put(e.getValue(),e.getKey());
}
The above code is the initialization. everytime you want to set things you need to do that
then you can achieve a random value with O(1) complexity
String getRandom(){
int i; /*random number between 0 to counter*/
return map.get(i);
}
Now to remove things you use map1 to achive it in constant time O(1);
void remove(String s){
if(!map1.containsKey(s))
return; //s doesn't exists
String val=map.get(counter); //value of the last
map.remove(counter) //removing the last element
int thisCounter= map1.get(s); //pointer to this
map1.remove(s); // remove from map1
map.remove(counter); //remove from map
map1.put(thisCounter,val); //the val of the last element with the current pointer
counter--; //reducing the counter by one
}
obviously the main issue here is to keep the synchronization ensured. but by carefully analyzing the code you should be able to do that.

How to make the return false if the arraylist already have the string present in class?

I'm new to coding.
How do I return a false if there is a string being added that's already in the arraylist?
For example, if you have a list of dog names in the class and you add new dog names in the list, but don't add it when the same dog name was already in the list?
The Solution:
You could use a for statement to iterate through your array list:
public static bool checkArray(string dogName)
{
for int i=0; i<arrayName.Length; i++) // basic for loop to go through whole array
{
if (arrayName[i] == dogName) //checks if array value at index i is the dog's name
{
return true; //if it is, return true
}
}
return false; //gone through whole array, not found so return false
}
This means you can call your method via
string Name = "myDogsName";
bool isAlreadyPresent = checkArray(Name);
Note
This is written in C#, and so other coding languages will slightly
differ in their syntax.
isAlreadyPresent will then contain a bool value if the dog is
present or not
I have written this (for learning purposes) in (possibly) an
inefficient way, but should allow you to understand what is happening
at each stage.
the i++
The i++ may confuse new programmers, but effectively it is the same as writing
i = i + 1;
This also works for i--;
i = i - 1;
Or even i*=2;
i = i * 2;

Comparing a string in a struct with a string in an array

I have an array of structs, one of the elements in the struct is a string, and i need to compare those strings with other strings in an array of 12 strings. strcmp does not seem to work for me. I know i need to make seperate function to compare the the strings and return the value as a bool, but cant figure out how to make the compare function work.
The struct
typedef struct{
char *hometeam[Max_number_of_chars], *awayteam[Max_number_of_chars];
int playround, date_day, date_month, date_year,
time_hour, time_minute, home_score, away_score, crowd_thousand,
crowd_hundred;
} match;
The array of strings
char *teams[Number_of_teams] = {"AGF","AAB","SDR","RFC",
"EFB","BIF","SIF","OB",
"FCK","FCM", "ACH","FCN"};
the line where i need the compare_function
if(compare_names(all_games[i].hometeam, teams[j])==0) {//crazy stuff}
EDIT: What i need help with is making function that compares the string value from *teams[j] with the string value from all_games[i].hometeam. But i dont know how to pass the specific part of the struct all_games[i].hometeam to the compare_function, where i want it to be a char string.
// Assuming char *teams[Number_of_teams] is globally defined.
int find_match(struct match)
{
for(i=0; i < Number_of_teams; i++){
if(strcmpi(match.hometeam, teams[i]) == 0){
return i;
}
}
return -1;
}
The logical flow of what you want to do isn't clear, but you can try something like above.

Binary search for specific value in array of structs

I wrote this function that uses a binary search to look for a specific value in an array of structs. Why doesn't it compile?
I'm getting this error:
prog.c:224: error: subscripted value is neither array nor pointer
prog.c:226: error: subscripted value is neither array nor pointer
This is the function:
int FieldSearch(Field *pArr, int size, int val)
{
int low=0,high=size-1, middle;
while (low <= high)
{
middle = (low + high)/2;
if (val == pArr->Id[middle])
return middle;
else if (val < pArr->Id[middle])
high = middle -1;
else
low = middle +1;
}
return NOT_FOUND;
}
This is the field struct:
typedef struct field
{
char Id;
Coordinates location;
int area;
int price;
} Field;
Maybe the prototype is wrong...
Your problem is this statement:
pArr->Id[middle]
It looks like, but I don't have nearly enough info, that your member Id is not a pointer or an array, but merely a variable. So you cannot access it with an operator[]. You should show us what this Field object looks like.
I'm guessing you should do something like this
(pArr + middle)->Id so this will access the element of the Field array you passed into your function. Then you do have to pass in an actual array of Field structures, for this to work.
If you want to search the "array" pArr, you need to put the brackets directly behind the identitifier. This should work:
pArr[middle].Id

Resources