The Code:
boost::unordered_map<int, boost::unordered_map<int, float>> map;
{
boost::unordered_map<int, float> h;
h.insert(make_pair(1, 0.5));
map.insert(make_pair(5, h));
}
{
boost::unordered_map<int, float> h = map[5];
h.insert(make_pair(2, 0.6));
map.insert(make_pair(5, h));
}
cout << map[5].size() << endl;
Why the output is 1 not 2?
And when i use boost::unordered_map* > instead, then everything works well.
Can anyone help me?
Here's what happens in the second block of code:
h = map[5] creates a copy of the inner map.
h.insert(...) adds a value to the copy of the inner map.
map.insert(...) does nothing. unordered_map::insert inserts an element to the map if and only if there is no element in the map with an equivalent key. But the key 5 is already present, and so no insertion happens. You can confirm this by checking that the boolean portion of the return value from the insert call is false.
At the end of the block, the copied map is discarded, and the original inner map, with a single value, remains in map. As a result, you get the output of map[5].size()==1.
But why do we get an output of 2 if the value type of the inner map is set to a pointer, boost::unordered_map<int, float>*? The second block of code would do this:
h = map[5] will get a pointer to the inner map inserted into map.
h.insert(...) adds a value to the inner map directly -- not into a copy. At this point, map[5].size()==2 already.
map.insert(...) still does nothing. But there's no need to -- the inner map was already modified in place.
Related
can I combine below closures into one or do this in a more functional and elegant way in groovy. I am using the sortMethod in some other places( for testing purpose) too.
for eg : countAndMap should take
["a b c a a c" , "b b c"] and return[x1 : [a:3,c:2,b:1] , x2 : [b:2,c:1]]
def countAndMap(List<String> stringList) {
stringList.withIndex().collect { String s, Integer i -> [(num.call(i)): count.call(s)] }
}
Closure count = {sortMethod.call(it.split().countBy {it}) }
Closure sortMethod = { it.sort { x, y -> x.value <=> y.value } }
Closure num = { "x ${it + 1}".toString()}
there are no errors but I wonder if it's possible to do it in a more functional way
I am not sure what you mean with "more functional", but you could use a fold operation (called inject in groovy):
list = ["a b c a a c" , "b b c"]
def createSortedHistogram(String toCount) {
toCount
.split() // Create list of words
.inject([:]){ acc, word -> acc[word] = 1 + (acc[word] ?: 0);acc} // create histogram
.sort{-it.value} // sort histogram map by value desc
}
def countAndMap(List<String> list) {
list.withIndex().collectEntries{ sublist, i -> ["x ${i+1}": createSortedHistogram(sublist)] }
}
countAndMap(list)
I think the most interesting part is the inject method.
This solution uses the initial value [:] in order to use a map as result. In each iteration the inject operation either adds a new entry with value 1 to the map (if the word/key does not exist in the map) or increases the value of the word/key if it is already present in the map.
See the inject definition from Collections GroovyDoc.
public Object inject(Object initialValue, Closure closure) - Iterates through the given Collection, passing in the initial value to the 2-arg closure along with the first item. The result is passed back (injected) into the closure along with the second item. The new result is injected back into the closure along with the third item and so on until the entire collection has been used. Also known as foldLeft or reduce in functional parlance.
I'm trying to generate HashMap object that will have properties and values set from parsed text input. Working fine with simple assigned, but wanted to make it more clever and use inject.
def result = new HashMap();
def buildLog = """
BuildDir:
MSBuildProjectFile:test.csproj
TargetName: test
Compile:
Reference:
""".trim().readLines()*.trim()
buildLog.each {
def (k,v) = it.tokenize(':')
result."${k.trim()}"=v?.trim()
}
println "\nResult:\n${result.collect { k,v -> "\t$k='$v'\n" }.join()}"
generates expected output:
Result:
Reference='null'
MSBuildProjectFile='test.csproj'
BuildDir='null'
TargetName='test'
Compile='null'
after replacing the insides of .each { } closure with injection:
it.tokenize(':').inject({ key, value -> result."${key}" = value?.trim()})
the results generated are missing unset values
Result:
MSBuildProjectFile='test.csproj'
TargetName='test'
Am I doing something wrong, tried with inject ("", {...}) but it seems to push may keys into values.
inject is basically a reduce. The reducing function takes two arguments, the result of the previous iteration or the initial value (e.g. the accumulator) and the next value from the sequence. So it could be made to work, but since you only expect one sequence value, it just convolutes the code.
I do see a great use for collectEntries here, as it allows you to create a Map using either small key/values map, or lists of two elements. And the latter you have:
result = buildLog.collectEntries {
it.split(":",2)*.trim()
}
should work for your code instead of buildLog.each
In the Go blog, this is how to print the map in order.
http://blog.golang.org/go-maps-in-action
import "sort"
var m map[int]string
var keys []int
for k := range m {
keys = append(keys, k)
}
sort.Ints(keys)
for _, k := range keys {
fmt.Println("Key:", k, "Value:", m[k])
}
but what if I have the string keys like var m map[string]string
I can't figure out how to print out the string in order(not sorted, in order of string creation in map container)
The example is at my playground http://play.golang.org/p/Tt_CyATTA3
as you can see, it keeps printing the jumbled strings, so I tried map integer values to map[string]string but I still could not figure out how to map each elements of map[string]string.
http://play.golang.org/p/WsluZ3o4qd
Well, the blog mentions that iteration order is randomized:
"...When iterating over a map with a range loop, the iteration order is not specified and is not guaranteed to be the same from one iteration to the next"
The solution is kind of trivial, you have a separate slice with the keys ordered as you need:
"...If you require a stable iteration order you must maintain a separate data structure that specifies that order."
So, to work as you expect, create an extra slice with the correct order and the iterate the result and print in that order.
order := []string{"i", "we", "he", ....}
func String(result map[string]string) string {
for _, v := range order {
if present in result print it,
}
... print all the Non-Defined at the end
return stringValue
}
See it running here: http://play.golang.org/p/GsDLXjJ0-E
I came across this bit of code:
n = args[0] as Long
[*n..1, n].any{ println ' '*it + '*'*(n - ~n - it*2) }
It's used for printing a tree form of structure. Like this:
*
***
*****
*******
*
(for n=4)
How does the code [*n..1,n] produce [4, 3, 2, 1, 4]?
How does any method works here? The Doc doesn't help me much. What is a predictive that can be passed to any(as mentioned in Doc's)?
Whats the use of any and how its handled in this case?
Q1a: * "unpacks" an array. .. creates a range. [] creates a collection.
Q1b: *n..1 unpacks [4,3,2,1] into its individual parts.
Q1c: [4,3,2,1,n] == [4,3,2,1,4]
Q2: I don't know why any was used here; each works just as well, and makes more sense in context. any does loop over the connection, so the println side-effect functions as intended.
Normally any would be used to determine if any collection elements met a criteria, for example:
[*n..1,n].any { it > 10 } // Returns false, no elements are > 10
[*n..1,n].any { it == 3 } // Returns true, because at least one element is 3
The last statement of the closure is used to determine if each item meets the criteria. println returns null, so any will return false. The value is unused and discarded.
The only reason I can think of that someone might have used any is to avoid seeing the return value of each in the console. each returns the original collection.
1) n..1 is called a range literal, it creates a groovy.lang.Range object that decrements by 1 from n to 1. This is then merged into the surrounding list context using the "Spread operator (*)"
2) the any method is defined in DefaultGroovyMethods and it is a predicate function that returns true if an element in a collection satisfies the supplied predicate closure. In this example, the code doesn't check the return value, so original other could have produced the same output using an each call instead.
I need some help understanding how stdext::hash_multimap's lower_bound, upper_bound and equal_range work (at least the VS2005 version of it).
I have the following code (summarized for the question)
#include <hash_map>
using stdext::hash_multimap;
using std::greater;
using stdext::hash_compare;
using std::pair;
using std::cout;
typedef hash_multimap < double, CComBSTR, hash_compare< double, greater<double> > > HMM;
HMM hm1;
HMM :: const_iterator it1, it2;
pair<HMM::const_iterator, HMM::const_iterator> pairHMM;
typedef pair <double, CComBSTR> PairDblStr;
// inserting only two values for sample
hm1.insert ( PairDblStr ( 0.224015748, L"#1-64" ) );
hm1.insert ( PairDblStr ( 0.215354331, L"#1-72" ) );
// Using a double value in between the inserted key values to find one of the elements in the map
it1 = hm1.lower_bound( 0.2175 );
if( it1 == hm1.end() )
{
cout << "lower_bound failed\n";
}
it1 = hm1.upper_bound( 0.2175 );
if( it1 == hm1.end() )
{
cout << "upper_bound failed\n";
}
pairHMM = hm1.equal_range( 0.2175 );
if( ( pairHMM.first == hm1.end() ) && ( pairHMM.second == hm1.end() ) )
{
cout << "equal_range failed\n";
}
As mentioned in the comment I am passing in a value (0.2175) that is in between the two inserted key values (0.224015748, 0.215354331). But the output of the code is:
lower_bound failed
upper_bound failed
equal_range failed
Did I misunderstand how the lower_bound, upper_bound and equal_range can be used in maps? Can we not find a "closest match" key using these methods? If these methods are not suitable, would you have any suggestion on what I could use for my requirement?
Thanks in advance for any help.
Thanks to #billy-oneal #dauphic for their comments and edits. I have updated the code above to make it compilable and runnable (once you include the correct headers of course).
Can we not find a "closest match" key using these methods?
No. hash_multimap is implemented using a hashtable. Two keys that are very close to each other (0.2153 and 0.2175, for example) will likely map to totally different bins in the hashtable.
A hashtable does not maintain its elements in a sorted order, so you cannot find the closest match to a given key without a linear search.
The lower_bound, upper_bound, and equal_range functions in hash_multimap have a somewhat odd implementation in the Visual C++ standard library extensions.
Consider the documentation for lower_bound:
The member function determines the first element X in the controlled sequence that hashes to the same bucket as key and has equivalent ordering to key. If no such element exists, it returns hash_map::end; otherwise it returns an iterator that designates X. You use it to locate the beginning of a sequence of elements currently in the controlled sequence that match a specified key.
And the documentation for upper_bound:
The member function determines the last element X in the controlled sequence that hashes to the same bucket as key and has equivalent ordering to key. If no such element exists, or if X is the last element in the controlled sequence, it returns hash_map::end; otherwise it returns an iterator that designates the first element beyond X. You use it to locate the end of a sequence of elements currently in the controlled sequence that match a specified key.
Essentially, these functions allow you to identify the range of elements that have a given key. Their behavior is not the same as the behavior of std::lower_bound or std::map::lower_bound (theirs is the behavior that you were expecting).
For what it's worth, the C++0x unordered associative containers do not provide lower_bound, upper_bound, or equal_range functions.
Would you have any suggestion on what I could use for my requirement?
Yes: if you need the behavior of lower_bound and upper_bound, use an ordered associative container like std::multimap.