I'm practicing leetcode problems to perfect my kotlin syntax and am wondering why this code doesn't work. My question specifically is why doesn't my courses hashmap populate with this code.
Prerequisites is an array in this form [[0,1][0,3][4,5][6,7]] and if I print my variables for pre and post they print what I expect
But I'm trying to turn courses into an adjacency matrix like this {0: [1,3], 4: [5], 6: [7]}
and instead it just prints an empty set every time
class Solution {
fun canFinish(numCourses: Int, prerequisites: Array<IntArray>): Boolean {
val courses = HashMap<Int, MutableList<Int>>().withDefault{ mutableListOf<Int>() }
for ((pre, post) in prerequisites){
courses[pre]?.add(post)
}
print(courses)
return false
}
}
stdout: {}
[] does not give you the default value
From the docs of withDefault:
This implicit default value is used when the original map doesn't contain a value for the key specified and a value is obtained with Map.getValue function
If you want to get the default value, you need to use getValue instead of the index operator.
Using the index operator, you would just get null and because of the the null-safe operator, the add operation would not even be executed.
If you take a look at the relevant source code, you can see that the funxtionality get is not changed when using .withDefault but only getOrImplicitDefault returns the default value.
Getting the default does not set anything
Furthermore, when accessing courses.getValue(pre) in the loop, the Map will be empty. Because of the withDefault, it will return a MutableList where you can add elements but getting such a list and adding elements to it will not add the list to the Map. Reading and accessing an element does not insert it.
Simple solution
If you want to make sure the element is present in the Map, you can use courses[pre]=course.getValue(pre) before reading courses[pre]?:
class Solution {
fun canFinish(numCourses: Int, prerequisites: Array<IntArray>): Boolean {
val courses = HashMap<Int, MutableList<Int>>().withDefault{ mutableListOf<Int>() }
for ((pre, post) in prerequisites){
courses[pre] = courses.getValue(pre)
courses[pre]?.add(post)
}
print(courses)
return false
}
}
If the entry is set already, it will be set to itself (no change) and if it isn't set, it will be set to the default value (empty list).
dan1st's answer covers it - your default list is just returned, not put and returned, so it's not part of the map - but here's a different take to get that functionality:
val courses = HashMap<Int, MutableList<Int>>().run {
withDefault{ key ->
mutableListOf<Int>().also { put(key, it) }
}
}
So basically using the withDefault wrapper, using run so the map is this in the default value function, so you can add your list to the map before returning it. Then when you call courses.getValue(69) you'll get back a list that's already been inserted into the map
If you like, there's also a function that'll do this grouping for you, groupBy
val nums = arrayOf(
intArrayOf(0,1),
intArrayOf(0,3),
intArrayOf(4,5),
intArrayOf(6,7)
)
val groups = nums.groupBy(keySelector = { it[0] }, valueTransform = { it[1] })
println(groups)
>> {0=[1, 3], 4=[5], 6=[7]}
Related
I am new in flutter and I want to use a Map inside a List of elements.
Basicaly,
var questions = [
{'key' : 'value'},
'anotherElement'
] ;
//and then trying to access it by //passing it into a widget
myWidget(
['value']
)
but this way is not working.
shows error:
The operator '[]' isn't defined for the type 'Object'.
Please let me know how can I use Map inside a List?
You have to specify the List type to Map and store the map values into the list collection. Please just refer the below code snippets. I just show you the simple codes to explain the list of map items.
void main() {
List<Map<String, int>> maps = [
{'one': 1, 'two': 2},
// Add more map records.
];
// Gets the first map item from the maps collection.
// and gets the value of 'one' key from it.
print(maps[0]['one']);. // Prints 1.
}
I have a list like the following:
val map_temp =
List(
(List("SRC_123","SRC_999"),"TRGT_123"),
(List("SRC_456"),"TRGT_456"),
(List("SRC_789"),"TRGT_789"),
(List("SRC_888"),"TRGT_888"),
)
I want to check whether SRC_999 exists in it.
I tried the following:
map_temp.foreach {
case(key, value) =>
if (key.contains("SRC_999")) {
print("yes exists")
}
}
This causes the following error
error: value contains is not a member of Any
case(key:Any, value) => if(key.contains("SRC_99"))
I have also tried this:
map_temp.foreach(a => if(a._1.contains("SRC_999")))
But this causes the following error:
error: value contains is not a member of Any
mapped.foreach(a => print(a._1.contains("SRC_999")))
How can I solve this?
How can I solve this?
By not having a List[Any].
By having a List[Any], you are explicitly telling Scala that the elements could be anything. That means Scala doesn't know anything about the elements. It doesn't even know whether they have a contains method or not. The elements could be integers, for example, which don't have a contains method.
The map_temp value is List[(List[String], String)], not List[Any]. You can check for the element you are looking for like this:
map_temp.exists(_._1.contains("SRC_999"))
This should do what you want:
val map_temp =
List(
(List("SRC_123","SRC_999"),"TRGT_123"),
(List("SRC_456"),"TRGT_456"),
(List("SRC_789"),"TRGT_789"),
(List("SRC_888"),"TRGT_888"),
)
def exists[A](input: List[(List[A], _)], what: A): Boolean =
input.exists(_._1.contains(what))
// should be found
assert(exists(map_temp, "SRC_999"))
assert(exists(map_temp, "SRC_888"))
// should not be found
assert(!exists(map_temp, "SRC_998"))
assert(!exists(map_temp, "TRGT_123"))
I don't think you actually have a List[Any] to begin with. It appears that you are experiencing a couple of type errors that could mislead you into believing so. Your map_temp is a List[(List[String], String)].
If that's not the case and you are getting map_temp from a method that for some reason returns a List[Any], if you're in control of that method you can change it to reflect the actual type. If you can't, even though it's not safe, you can attempt to cast it.
With few changes, you can also retrieve items:
def find[A, B](input: List[(List[A], B)], what: A): Option[B] =
input.find(_._1.contains(what)).map(_._2)
// should be found
assert(find(map_temp, "SRC_999") == Some("TRGT_123"))
assert(find(map_temp, "SRC_888") == Some("TRGT_888"))
// should not be found
assert(find(map_temp, "SRC_998") == None)
assert(find(map_temp, "TRGT_123") == None)
You can play around with this code here on Scastie.
I am coming from a javascript background, and in javascript if i had an array with elements [1,2,3] I can map through this array and perform a function on each iteration as so:
[1,2,3].map((i) => {
console.log(i);
return;
})
and i get
1
2
3
Trying same in dart
void main() {
[1, 2, 3].map((i) {
print(i);
return;
});
}
No output is printed, what am I missing?
JavaScript is different from Dart.
According to the documentation, the map method on an Iterable is meant to
return a new lazy Iterable with elements that are created by calling f on each element of this Iterable in iteration order.
In other words, the function in the map method isn't called until it is needed because it is lazily invoked. It will not return anything until something asks for what it is supposed to return. As long as the returned Iterable is not iterated over, the supplied function f will not be invoked.
Try in dartpad.dev
void main() {
var arr = [1, 2, 3];
var arr2 = arr.map((item)=> {
item * 2
});
print ('$arr2');
}
In the example above, the function in the map method of arr is called/invoked because it is requested for by $arr2 in the print function. Because of this, it runs the code inside it and the parameter in the print method gets printed out
Try
print([1, 2, 3].map((i) {
print(i);
return;
}));
You'll see that you get your desired result, because the function in the map method was invoked by the print method.
Since the method is lazy, it will not be invoked until it is requested. Adding a map method to an array doesn't invoke it. You've got to require what it returns for the function in the map method to be invoked.
I have a class in my model that includes a list of bool. From my UI I want to set the bool state in just a single item in the list via a setter (so that I can also save it). I can't figure out the syntax (or whether this is a valid thing to do).
///This is OK
set notificationDismissed(bool notificationDismissed){
_notificationDismissed = notificationDismissed;
saveParameterBoolean(_notificationDismissedKey,
_notificationDismissed);
}
bool get notificationDismissed => _notificationDismissed;
///This is OK too
List<bool> get questionsAnswered => _questionsAnswered;
set questionsAnswered(List<bool> questionsAnswered){
_questionsAnswered = questionsAnswered;
for(int i=0; i<_questionAnsweredParamKeys.length; i++ ){
saveParameterBoolean(_questionAnsweredParamKeys[i],
_questionsAnswered[i]);
}
updateState();
}
///This is not OK !!!! but should show what I want to do
List<bool> get questionsAnswered[index] => _questionsAnswered[index];
set questionsAnswered[index](bool questionsAnswered[index]){
_questionsAnswered[index] = questionsAnswered[index];
saveParameterBoolean(_questionAnsweredParamKeys[index],
_questionsAnswered[index]);
updateState();
}
I know I'm missing something obvious here, any help greatly appreciated
get and set functions can't take any arguments. The simplest approach would be to use normal functions:
bool getQuestionsAnswered(int index) => _questionsAnswered[index];
void setQuestionsAnswered(int index, bool value) {
_questionsAnswered[index] = value;
saveParameterBoolean(_questionAnsweredParamKeys[index], _questionsAnswered[index]);
updateState();
}
Another alternative would be to change _questionsAnswered from a List to a custom class that implements operator [] (to get an element) and operator []= (to set an element), and then you could make them do whatever you want.
I want to have an immutable list, since I don't really need the mutability so it likely to just cause bugs. However, the list is a lateinit var declared at the class level.
I want to initially populate the list with values from a loop somewhat like this:
for (items in someOtherCollection) {
val itemToAdd = doSomeProcessingOnThisData()
list.add(itemToAdd)
}
However, since the list is immutable, I can't call add(). Is there a better way to init a list such as this without simply adding all the values to a second, mutable list and then assigning it to an immutable list?
My current solution is this, but it just seems inefficient:
val tmpList = mutableListOf<Data>()
foos.forEach() {
val itemToAdd = doSomeProcessing()
foos.add(itemToAdd)
}
this.list = tmpList
If you want to make a new list processing some data in another collection, try this:
this.list = someOtherCollection.map {
doSomeProcessing()
}
Give this a read for a better understanding: https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/map.html