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

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!

Related

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;

C++\Cli Parallel::For with thread local variable - Error: too many arguments

Trying to implement my first Parallel::For loop with a tread local variable to sum results of the loop. My code is based on an example listed in "Visual C++ 2010, by W. Saumweber, D. Louis (German). Ch. 33, P.804).
I get stuck in the implementation with syntax errors in the Parallel::For call. The errors are as follows, from left to right: a) expected a type specifier, b) too many arguments for generic class "System::Func", c) pointer to member is not valid for a managed class, d) no operator "&" matches these operands.
In line with the book, I create a collection with data List<DataStructure^> numbers, which is subject to a calculation performed in method computeSumScore which is called by the Parallel::For routine in method sumScore. All results are summed in method finalizeSumScore using a lock.
Below I paste the full code of the .cpp part of the class, to show what I have. The data collection "numbers" may look a bit messy, but that's due to organical growth of the program and me learning as I go along.
// constructor
DataCollection::DataCollection(Form1^ f1) // takes parameter of type Form1 to give acces to variables on Form1
{
this->f1 = f1;
}
// initialize data set for parallel processing
void DataCollection::initNumbers(int cIdx)
{
DataStructure^ number;
numbers = gcnew List<DataStructure^>();
for (int i = 0; i < f1->myGenome->nGenes; i++)
{
number = gcnew DataStructure();
number->concentrationTF = f1->myOrgan->cellPtr[cIdx]->concTFA[i];
number->stringA->AddRange(f1->myGenome->cStruct[i]->gString->GetRange(0, f1->myGenome->cChars));
number->stringB->AddRange(f1->myGenome->cStruct[i]->pString);
if (f1->myGenome->cStruct[i]->inhibitFunc)
number->sign = -1;
else
number->sign = 1;
numbers->Add(number);
}
}
// parallel-for summation of scores
double DataCollection::sumScore()
{
Parallel::For<double>(0, numbers->Count, gcnew Func<double>(this, &GenomeV2::DataCollection::initSumScore),
gcnew Func<int, ParallelLoopState^, double, double>(this, &GenomeV2::DataCollection::computeSumScore),
gcnew Action<double>(this, &GenomeV2::DataCollection::finalizeSumScore));
return summation;
}
// returns start value
double DataCollection::initSumScore()
{
return 0.0;
}
// perform sequence alignment calculation
double DataCollection::computeSumScore(int k, ParallelLoopState^ status, double tempVal)
{
int nwScore;
if (numbers[k]->concentrationTF > 0)
{
nwScore = NeedlemanWunsch::computeGlobalSequenceAlignment(numbers[k]->stringA, numbers[k]->stringB);
tempVal = Mapping::getLinIntMapValue(nwScore); // mapped value (0-1)
tempVal = (double) numbers[k]->sign * tempVal * numbers[k]->concentrationTF;
}
else
tempVal = 0.0;
return tempVal;
}
// locked addition
void DataCollection::finalizeSumScore(double tempVal)
{
Object^ myLock = gcnew Object();
try
{
Monitor::Enter(myLock);
summation += tempVal;
}
finally
{
Monitor::Exit(myLock);
}
}
Once this problem is solved I need to ensure that the functions called (computeGlobalSequenceAlignment and getLinIntMapvalue) are thread safe and the program doesn't get stalled on multiple treads accessing the same (static) variables. But this needs to work first.
Hope you can help me out.
Hans Passant answered my question in the comments (include full method name, add comma). Yet I cannot mark my question as answered, so this answer is to close the question.

Count of nodes in BST

I am trying to count the number of nodes in a Binary Search Tree and was wondering what the most efficient means was. These are the options that I have found:
store int count in the BST Class
store int children in each node of the tree which stores the number of children under it
write a method that counts the number of Nodes in the BST
if using option 3, I've written:
int InOrder {
Node *cur = root;
int count = 0;
Stack *s = null;
bool done = false;
while(!done) {
if(cur != NULL) {
s.push(cur);
cur = cur->left;
}
else {
if(!s.IsEmpty()) {
cur = s.pop();
count++;
cur = cur->right;
}
else {
done = true;
}
}
}
return count;
}
but from looking at it, it seems like it would get stuck in an infinite loop between cur = cur->left; and cur = cur->right;
So which option is the most efficient and if it is option 3, then will this method work?
I think the first option is the quickest and it only requires O(1) space to achieve this. However whenever you insert/delete an item, you need to keep updating this value.
It will take O(1) time to get the number of all the nodes.
The second option would make this program way too complicated since deleting/inserting a node somewhere would have to update all of its ancestors. Either you add a parent pointer so you can adequately update each one of the ancestors, or you need to go through all the nodes in the tree and update the numbers again. Anyway I think this would be the worst option of all three.
The third option is good if you don't call this many times since the first option is a lot quicker, O(1), than this option. This will take O(n) since you need to go through every single node to check the count.
In terms of your code, I think it's easier to write in a recursive way like below:
int getCount(Node* n)
{
if (!n)
return 0;
return 1 + getCount(n->left) + getCount(n->right);
}
Hope this helps!

Remove key/value from map while iterating

I'm creating a map like this:
def myMap = [:]
The map is basically an object for a key and an int for a value. When I iterate over the map, I decret the value, and if it's 0, I remove it. I already tried myMap.remove(), but I get a ConcurrentModificationError - which is fair enough. So I move on to using it.remove(), which is giving me weird results.
Basically, my code is this:
myMap.each {
it.value--;
if( it.value <= 0 )
it.remove();
}
Simple enough. My problem is, if I print myMap.size() before and after the remove, they're the same. If I call myMap.containsKey( key ), it gives me true, the key is still in there.
But, if I print out the map like this:
myMap.each { System.out.println( "$it.key: $it.value" ); }
I get nothing, and calling myMap.keySet() and myMap.values() return empty.
Anyone know what's going on?
This should be a bit more efficient than Tim's answer (because you only need to iterate over the map once). Unfortunately, it is also pretty verbose
def map = [2:1, 3:4]
def iterator = map.entrySet().iterator()
while (iterator.hasNext()) {
if (iterator.next().value - 1 <= 0) {
iterator.remove()
}
}
// test that it worked
assert map == [3:4]
Can you do something like this:
myMap = myMap.each { it.value-- }.findAll { it.value > 0 }
That will subtract one from every value, then return you a new map of only those entries where the value is greater than zero.
You shouldn't call the remove method on a Map Entry, it is supposed to be a private method used internally by the Map (see line 325 for the Java 7 implementation), so you calling it yourself is getting the enclosing Map into all sorts of bother (it doesn't know that it is losing entries)
Groovy lets you call private methods, so you can do this sort of trickery behind the back of the Java classes
Edit -- Iterator method
Another way would be:
myMap.iterator().with { iterator ->
iterator.each { entry ->
entry.value--
if( entry.value <= 0 ) iterator.remove()
}
}

Resources