Ive got a function named allAppointmentList to get Appointments from the server using a GET method in AppointmentProvider class.
In my MyAppointments class I have initialized 2 lists named as appointment and allAppointments as below,
class _MyAppointmentState extends State<MyAppointment> {
bool isLoading = true;
List<Appointment> allAppointments=[];
List<Appointment> appointments = [];
And in the init state I have assigned the data I get from the allAppointmentList method to the 2 lists mentioned above.
#override
void initState() {
super.initState();
_loadAppointments();
}
_loadAppointments() async {
final AppointmentProvider appointmentProvider =
Provider.of<AppointmentProvider>(context, listen: false);
await appointmentProvider.getAllAppointments();
setState(() {
isLoading = false;
appointments = appointmentProvider.allAppointmentList;
allAppointments = appointmentProvider.allAppointmentList;
});
}
when I change one list the other changes as well.For example,
if I clear the appointments list,allAppoitments list gets cleared as well.If I remove the element in the second index of the appointments list,the element in the second index of the allAppointments list gets removed as well.
How can I make these two list act independently ?
Your problem is probably that you think this creates new lists:
appointments = appointmentProvider.allAppointmentList;
allAppointments = appointmentProvider.allAppointmentList;
My guess is that appointmentProvider.allAppointmentList returns the same List instance every time which is a problem here since you are then just assigning the same List object to both appointments and allAppointments.
I am not sure if you also want copies of all the objects inside the lists but if you just want to have independent lists which then contains references to the same objects, the safest would just be to do:
appointments = appointmentProvider.allAppointmentList.toList();
allAppointments = appointmentProvider.allAppointmentList.toList();
This will create new lists which then contains the same objects from appointmentProvider.allAppointmentList. But you can then delete/add elements to each of these lists without this change also happening to the other lists.
appointments and allAppointments are currently just references to appointmentProvider.allAppointmentList. You can create new instances as follows:
appointments = [...appointmentProvider.allAppointmentList];
allAppointments = [...appointmentProvider.allAppointmentList];
This uses a list literal [] in combination with the spread operator ... to create a new list with the same elements. Note that the elements themselves are still references to their original instances and are not deep copies.
Related
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]}
I'm new to programming so am probably missing something simple.
My aim is to call on a list from a result stored in a variable and pull a random entry from that List. The result 'categoryResult' is the correct List name but [random] is showing a single letter within the List name. When 'categoryResult' is replaced with hard code everything works as it should.
void getQuestion() async {
categoryResult = category[catNo];
final questions = await _firestore
.collection('questions')
.document(category[catNo])
.collection(categoryResult[random])
.document('question')
.get();
newQuestion = questions.data['$questionNumber'];
}
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
import groovy.transform.EqualsAndHashCode;
#EqualsAndHashCode(includes="name")
class Activity {
public String name
public buildings = []
public rooms = [] as Set
Activity(name) {
this.name = name
}
}
thisActivity=new Activity("activity")
activityRegistry = []
// is false correct
activityRegistry.contains(thisActivity)
// add new item activity2
activityRegistry << new Activity("activity2")
// is true?????
activityRegistry.contains(thisActivity)
this code is pretty straight forward, I create an activityRegistry list, I compare empty list to object I created. naturally test fails. I create a new object on the fly using new that I insert into the list. I compare the list then to the first object created, which is not part of the list, and contains, or in passes. could someone shed some light on how? or why?
The AST "EqualsAndHashCode" only use 'properties' from the class. Properties, in groovy, are declared without a modifier ('public'), and getter/setter are automatically generated.
In your example, change public String name to String name.
See : What are 'properties' in Groovy?
I'm sure there is a way to do this, but I'm really stuck on this one.
I have a domain model that connects to entities Foo and Bar in a many-to-many-relationship. Now when I want to list all Foos to a certain Bar, I do the query and get a lot of FooBar objects. I iterate through these objects and add all Foos to a list.
Like so:
def fooBarRelations = FooBar.findAllByBar bar
def fooList = []
fooBarRelations.each { fooList.add it.foo }
How can I sort the fooList based upon the parameters a g:sortableColumn adds to the url namely sort (the field to sort) and order.
I know you can pass the parameters to the query directly but I think this is not possible in my case?
So how can I either
Make one query without list iterating so I can pass in the sorting parameters OR
Sort my custom list based upon the sorting parameters?
Addition 1 (03/25/2012)
If I could to this ...
def fooBarRelations = FooBar.findAllByBar bar, [sort: 'foo.' + params.sort, order: params.order]
... the problem would be solved. But passing this to the query does not have any effect on the output. Is there any way I can sort a query by a sub-property?
If you really can't sort within the query itself. Then you need a list of lists.
List<List<Fields>> mylist;// where List<Fields> is a lists of the fields.
Then use a Comparator to sort your List> by the desired filed. Say your desired field is at index 3:
new Compare(List<Fields> L1, List<Fields> L2){
if(L1.get(3)>L2.get(3))
return -1;//etc.
UPATE BASED ON COMMENT:
say your entity is as follows
public class Entity{
String name, address, school;
Integer bankaccount;
//etc...
}
Then
public class WhereISort{
List<Entity> myList;
String mysorter;//mysorter can be declared here as static final
public WhereISort(){//maybe pass list in here or whatever
}
public Response myWebService(params..., String sorter){
mysorter=sorter;//mysorter can be declared here as static final
Collections.sort(myList, new Comparator() {
public int compare(Entity e1, Entity e2) {
if(mysorter.equalsIgnoreCase("name")){
return e1.getName().compareToIgnoreCase(e1.getName());
}else if(mysorter.equalsIgnoreCase("bankaccount")){
//your code here, etc.
}
}
});
}
}
Of course, the main point is using "mysorter" and the inner class "Comparator" to sort