Weird behavior when set Array of Strings to HashMap in Kotlin - kotlin

I'm tryna add to HashMap Array of Strings but instead of normal Array of String I see only address in memory of String in console.
val map = mapOf<String, Array<String>>()
val list = listOf("sport")
val array = list.toTypedArray()
map["key"] to array
And Array after this operation converts in smth like this — [Ljava.lang.String;#518ed9b4
But expected to see this kind of behavior:
map["key"] -> array("sport")
What's the problem might be with this sample of code?

Arrays in Java/Kotlin don't have a good automatic conversion to strings (technically, their implementation of toString()). What you see is your array, but instead of showing the contents, it only says it is an array of strings and shows the memory address.
To show the contents of an array you can use builtin contentToString() extension or wrap it into a list:
println(arrayOf("sport").contentToString())
println(arrayOf("sport").asList())
BTW, I believe there is a mistake in your example. map["key"] to array doesn't do anything, it should be probably map["key"] = array. Also, map in your example is read-only, you can't add items to it. However, as you already got to the point you print an array, I assume your real code is a little different.

Related

Why does 'indexOf' not find the specified arrayOfLong?

I have an ArrayList of LongArrays, each of size 2. I am trying to use the built-in 'indexOf' method to find the index of a specific array of longs, and I can't figure out why the code says the array of longs I'm searching for isn't found. See the below screen shot of a debugging session where try to evaluate finding 'longArrayOf(0L,5L)' in the ArrayList. In my mind, longArrayOf(0L,5L) is clearly the first element in the cardHierarchy array. Can the 'indexOf' function not be used for finding arrays? Can anyone suggest an alternate method?
indexOf uses Object.equals() when you pass arrays, which compares by reference address which is different for the LongArray passed to indexOf and the one present in cardHierarchy.
Change it to
cardHierarchy.indexOfFirst { it.contentEquals(longArrayOf(0L, 5L)) }

looping through NSStringEncoding(enum) value

I currently write some code to decode string using NSStringEncoding.
And I'd like to decode that string using all value of NSStringEncoding.
But I don't know how to get all value of NSStringEncoding.
I checked this article, but values of NSStringEncoding it not continuous,
so I'm looking for better solution.
looping through enum values
Anyone have good idea??
You can use NSString's class method availableStringEncodings which:
Returns a zero-terminated list of the encodings string objects support in the application’s environment.
Described another way a "zero-terminated list" is a pointer to a C-array. You can iterate over this array.
HTH

Understanding Solr charTermAttr methods

I can across a copy methods from charTermAttr from the org.apache.lucene.analysis.tokenattributes.CharTermAttribute library.
Can anyone explain what copyBuffer and buffer does for charTermAttr? The documentation isn't very clear. If you could provide an example that would be great too!
CharTermAttributeImpl keeps internally a char array and a length variable that represents the internal term.
The copyBuffer method writes over this array by using the char array provided with the respective offset and length params.
The buffer method returns the internal array that you can directly modify. Additionally, you can get the term representation as a string by calling the attribute's toString method
Have a look at the javadocs for more details: http://lucene.apache.org/core/4_9_0/core/org/apache/lucene/analysis/tokenattributes/CharTermAttribute.html

d2: assigning ranges/iterators to array slices

Consider following code:
enum size = 16;
double[size] arr1 = [...];
double[size] arr2 = [...];
process = (double x) { return (x + 1); };
arr2[] = map!(process)(arr1[]); // here
I have trouble converting results of map back to my plain array. Problem applies not only to map, but also to take, repeat and all those fine tools from std.algorithm and std.range that operate on ranges.
On this assignment, I get Error: cannot implicitly convert expression (map(arr1[])) of type Result to double[]. How can I evaluate range to array without using
uint i = 0;
foreach (x; map!(process)(arr1[])) {
arr2[i] = x;
i++;
}
?
Additionally, can someone please explain, why I must call map!(process)(arr1[]) instead of map!(process)(arr1) with static arrays? Shouldn't static arrays be compatible with dynamic for means of iteration, or I don't get something?
Also, it seems that straightforward enumeration syntax foreach (index, item; sequence) does not work for ranges - are there workarounds? I guess the reason is the same as why ranges cannot be assigned to array slices.
Functions such as map and filter return ranges, not arrays, so simply assigning to an array isn't going to work any more than assigning a string to wstring is going to work. They're different types. And for many range-based functions (including map and filter), the ranges they return are actually lazy in order to avoid unnecessary computation, which makes them that much less compatible with an array. The solution is to use std.array.array, which takes a range and creates a dynamic array from it. So, you could do
auto arr = array(map!process(origArray));
However, I would advise not converting a range into an array before you actually need to, since it can result in unnecessary computations, and it means allocating a new array. If you actually need an array, then by all means, use std.array.array to convert the range, but operating on the range can often be more efficient if you don't need an actual array. However, if you want to convert the result to a static array as opposed to a dynamic one, you're probably better off just assigning each element in a loop (and maybe skipping map altogether), since using std.array.array will then have allocated a dynamic array that you won't be using once you've assigned to the static array. It's a waste of memory.
Also, be aware that using static arrays with range-based functions can be risky in that they must slice the static array to get a dynamic array for the range-based functions to process, and if that dynamic array escapes the scope that the static array was declared in, then you're leaking references to data which no longer exists. For example,
auto func()
{
int[5] arr;
return map!process(arr[]);
}
would be very bad. However, as long as you're done using the slice and nothing refers to it anymore (including any ranges that might have been created) before you exit the scope with the static array in it, you should be fine. It is something to be careful of though.
As for the question about having to slice static arrays, you really should ask that as a separate question, but two existing questions that relate to it are this one and this one. What it pretty much comes down to is that IFTI (Implicit Function Template Instantiation) instantiates using the exact type that it's given, and a static array is neither a dynamic array nor a range, so any templated function which specifically requires a dynamic array or a range will fail to compile with a static array. The compiler will implicitly slice static arrays to convert them to dynamic arrays for functions which explicitly take dynamic arrays, but those sort of implicit conversions don't happen with template instantiation, so you must explicitly slice static arrays to pass them to range-based functions.
As for the question about using foreach with indices and ranges, again, you shouldn't be asking multiple questions in the same question. Please post separate questions for each question that you have. What it comes down to though is that
foreach(elem; range)
{
//stuff
}
gets lowered to something close to
for(; !range.empty; range.popFront())
{
auto elem = range.front;
//stuff
}
And that doesn't involve indices at all. It could be change to create an index variable for you, but it doesn't always make sense for ranges to have their index iterating by one like that on every iteration (much as it usually would be fine), and so that hasn't been done. It's simple enough to add your own counter though.
{
size_t i;
foreach(elem; range)
{
//stuff
++i;
}
}
opApply does support using indices with foreach, but it isn't a range, and doesn't work with range-based functions.

How to preallocate an array of class in MATLAB?

I have an array of objects in MATLAB and I've called their constructors in a loop:
antsNumber = 5;
for counter = 1: antsNumber
ant(counter) = TAnt(source, target);
end
MATLAB warns me to use preallocation to speed up the process. I do know the benefits of preallocation but I don't know how to do that for objects.
Here are a few options, which require that you design the class constructor for TAnt so that it is able to handle a no input argument case:
You can create a default TAnt object (by calling the constructor with no input arguments) and replicate it with REPMAT to initialize your array before entering your for loop:
ant = repmat(TAnt(),1,5); %# Replicate the default object
Then, you can loop over the array, overwriting each default object with a new one.
If your TAnt objects are all being initialized with the same data, and they are not derived from the handle class, you can create 1 object and use REPMAT to copy it:
ant = repmat(TAnt(source,target),1,5); %# Replicate the object
This will allow you to avoid looping altogether.
If TAnt is derived from the handle class, the first option above should work fine but the second option wouldn't because it would give you 5 copies of the handle for the same object as opposed to 5 handles for distinct objects.
The following link might be of help:
http://www.mathworks.com/help/techdoc/matlab_oop/brd4btr.html#brd4nrh
Web archive of dead link
New link:
http://de.mathworks.com/help/matlab/matlab_oop/creating-object-arrays.html
The warning it gives is superfluous, unless you are doing computational heavy stuff, I would ignore it.
The reason why it's giving you the error, is because it has to find new space. Say, I give you a list of seven objects, and I tell you that you need to place them all in a row, I then go off, and give you a few more things you need to put somewhere. I then give you an eighth object and tell you to put it right after the seventh. Because you have stuff where the eighth object is, you either have to move it out of the way, or you have to move all seven objects. Matlab, is telling you it would be faster if you were to tell it beforehand that you want to put 5 things in there, rather than just giving it things one by one, having to look for a new spot each time. You can do that by adding this line to the top of your code:
ant = [1:5];
There are also other ways to do this too.
Not sure if I got your problem right, but if you want to initialize an array of your self-defined class "TAnt", here is how I would do it
For TAnt's constructor method, put something like:
function obj = TAnt(source, target)
if nargin > 0
obj.mySource = source;
obj.myTarget = target;
else
obj.mySource = defaultValue;
obj.myTarget = defaultValue;
end
end
Then to initialize/pre allocate an array of default TAnt objects,
ants(1,n) = TAnt(); % n is the length of your ants array