Is it possible to make a TreeMap from a Map literal? - dart

I have a Map literal, an I want it to be a TreeMap, but by default I believe it's a LinkedHashMap. Casting a LinkedHashMap to a TreeMap won't work as it's not a subtype.
Basically, I'm looking for the simplest way to make this work:
var map = <int, int>{for(int i = 0; i < intervals.length; i++) intervals[i][0] : i} as SplayTreeMap;
As mentioned before, casting as SplayTreeMap won't work as they types don't align.
Thanks much in advance

Use the SplayTreeMap.from constructor to create a SplayTreeMap. There isn't any way to cast it as you said.
Remove the as from your current code and add this to get your SplayTreeMap:
var newMap = SplayTreeMap.from(map);
Depending on your key type and your use case, you can pass compare and isValidKey parameters as well. Full constructor definition:
SplayTreeMap<K, V>.from(
Map other,
[int compare(
K key1,
K key2
),
bool isValidKey(
dynamic potentialKey
)]
)

Related

Missing Dart null checking shorthand?

I know that Dart has the null checking shorthands
x = y ?? z;
and
x = y?.z;
But what if I have a statement like
x = (y != null) ? SomeClass(y) : z;
I don't want to pass null to the SomeClass constructor - so in that case I want x to be set to z (in my specific situation z happens to be null).
I can't figure out how/if I can use any of the shorthands in this scenario, or if I'm stuck with the direct null check.
The short answer is: there is no shorthand. Your code is good.
The really short answer is: it depends. ;)
If you think about the surrounding codebase you can come up with a different architecture overall.
You may as well pass null to the constructor
x = SomeClass(y);
and then give a reasonable default in your initializer list:
class SomeClass {
dynamic _value;
SomeClass(value) _value = value ?? '';
}
or throw an exception:
var nullError = Exception('Null value not allowed');
class SomeClass {
dynamic _value;
SomeClass(value) _value = value ?? (throw nullError);
}
though a more idiomatic way would be this:
class SomeClass {
dynamic _value;
SomeClass(value) {
ArgumentError.checkNotNull(value);
_value = value;
}
As I know nothing about the rest of your code, I cannot give you the right answer.
But I suggest you to ask yourself:
Where does this z value come from? What is its meaning?
(If you're in big project, you may use Dependency Injection or Factories.)
Maybe I have a view component, where empty strings are more useful than nulls?
These are some things I would ask myself.
But if you're hacking a quick script, this maybe a long shot.
You may have already finished your task by now, and maybe you really had no need for a shorthand in the first place.

Easiest way to convert a string into a HashMap

if I have some text in a String like:
"abc=123,def=456,ghi=789"
how could I create a populated HashMap<String,Int> object for it in the easiest, shortest amount of code possible in Kotlin?
I can think of no solution easier than this:
val s = "abc=123,def=456,ghi=789"
val map = s.split(",").associate {
val (left, right) = it.split("=")
left to right.toInt()
}
Or, if you need exactly a HashMap, use .associateTo(HashMap()) { ... }.
Some details:
.associate { ... } receives a function that produces pairs which are then stored into a map as keys and values respectively.
val (left, right) = it.split("=") is the usage of destructuring declarations on the list returned from it.split("="), it takes the first two items from the list.
left to right.toInt() creates a Pair<String, Int> defining a single mapping.
You can map each key/value to a Pair with the to keyword. An iterable of Pair can be mapped to a Map easily with the toMap() extension method.
val s = "abc=123,def=456,ghi=789"
val output = s.split(",")
.map { it.split("=") }
.map { it.first() to it.last().toInt() }
.toMap()

Dart type castings

I try to implement mergeSort in dart. Here is my code:
List mergeSort(List list)
{
if (list.length <= 1) return list;
List left, right, result;
int middle = list.length ~/ 2;
left = mergeSort(list.getRange(0, middle));
right = mergeSort(list.getRange(middle, list.length) as List);
result = merge(left, right);
return result;
}
And I get an TypeError at this line:
left = mergeSort(list.getRange(0, middle));
It seems that getRange() returns Iterable, but List implements Iterable what is the problem here, shouldn't it work?
Anyway when I try:
left = mergeSort(list.getRange(0, middle) as List);
it still doesn't work and gives me a CastError.
So my question is what's the problem here, and what's the Dart-style solution for it?
Thx in advance.
Iterable.toList() should do the trick.
left = mergeSort(list.getRange(0, middle).toList());
You can't directly cast an Iterable to a List because Iterable is a super type of List.
You can cast an object to its parent class, but you cant cast an object to any of its child class.
Example:
var a = new AnyClass();
var o = new Object(); //Actually this is not correct, but let's imagine
(o as AnyClass).toString() //wont works
(a as Object).toString() //will works
The getRange method returns an Iterable, not a List. Using as List does not change that, it just fails because its operand isn't actually a List.
You can use the List.sublist method to get a slice of a list as an actual List.
The collection package on pub also contains an implementation of merge-sort: package:collection/algorithms.dart.

Grails data binding to command object with maps - convert key to number

I have a Grails command object with a list of maps. The map key is intended to be a numeric domain object ID.
class MyCommand {
def grid = [].withDefault { [:] }
}
Data binding to the list/map is working in general because of the dynamic list expansion.
However, in the POST, the map keys are being bound as Strings and I want them to be Longs, as they are when the form is initially populated. I want foo[123] in my map, not foo['123'].
Alternatively I would be satisfied if the [] operators found the correct value given a numeric ID key to look up. In other words, if I could get foo[123] to return the same value as foo['123'], that would work too.
Any way to get this to work the way I want to? Maybe strongly type the map?
Or a better approach?
You can inject the property into the map to convert a String key to Long. For example:
def myMap = [:] << ['1': "name"] << ['Test': "bobo"]
def result = myMap.inject([:]){map, v ->
def newKey = v.key.isNumber() ? v.key.toLong() : v.key
map[newKey] = v.value
map
}
assert myMap['1'] == 'name'
assert result[1L] == 'name'
assert result['Test'] == 'bobo'

Classic asp: why doesn't Request.QueryString("foo").toString() work in a javascript (JScript) based page?

All I want to do is
Get the name-value pairs that were supplied to Request.QueryString
Populate a javascript object (aka hash) with keys from the names and values from the values
Halt the page if one of the expected hash values is the empty string
The Request.QueryString object is reminding me why I hated classic asp even before it was an abandoned technology. :/
The Request.QueryString collection has an awkward interface, particularly when it comes to iterating or cases where there are multiple params with the same name. I suggest grabbing the whole querystring using Request.QueryString.Item() or Request.ServerVariables('QUERY_STRING') and parse it using unescape/decodeURIComponent. It's a bit of effort, but gives you more control and consistency.
A simple example that lowercases keys:
var params = parseQueryString(Request.QueryString.Item());
function parseQueryString(qs) {
var parsed = {}, pairs = qs.split('&');
for (var i = 0; i < pairs.length; i ++) {
var pair = pairs[i], pos = pair.indexOf('=');
if (pos < 0) pos = pair.length;
parsed[unescape(pair.slice(0, pos)).toLowerCase()] = unescape(pair.slice(pos + 1));
}
return parsed;
}
Querystring contents are treated as string by default i believe..
But if you have to, you can always do String( request.querystring("foo") );
Are the keys known before-hand ? or you want to iterate through the pairs and retrieve both key and value ?

Resources