Flutter/Dart global List variable changed in a foreach loop is unchanged after the loop - flutter

I have a list declared outside a for loop and then I assign some values to this list inside that for loop and its value is updated when printed inside the loop but when I print it after the loop, it gives me an empty list.
List<List<String>> chunkSizeCollection(List<String> followedList) {
int counter = 0;
int ongoingCounter = 0;
bool isLessThanTen = false;
List<List<String>> returnAbleChunkedList = [];
List<String> midList = [];
log("in followedlist");
followedList.forEach((element) {
if (counter == 0) {
int difference = followedList.length - ongoingCounter;
if (difference < 10) {
// log("in difference if: $difference");
isLessThanTen = true;
}
}
midList.add(element);
counter++;
ongoingCounter++;
if (counter == 10 || (isLessThanTen && ongoingCounter == followedList.length)) {
returnAbleChunkedList.add(midList);
log("returnAbleChunkedList in counter 10 after adding new val is: $returnAbleChunkedList");
//above log works properly and prints the updated list
midList.clear();
counter = 0;
}
});
//this log on the other hand, returns an empty list
log("returnAbleChunkedList: $returnAbleChunkedList before return");
return returnAbleChunkedList;
}
The output:
[log] returnAbleChunkedList in counter 10 after adding new val is: [[KQTuEPllbmRrlBNvYgZ7oUXwtA63, OZUZOE10IzT8quUFoZbNxZOynU32, fCYIlYemCvbLTc7SpNHw6fCHrcm1, CbcLrtDNOdYZyC23FzEehOrJbKx2, FFvvVHCpPGNKUiXPQD34QdoPqH32, Gk09y59vSVXa1HNhzYvc6Atqnt53, JDO356z8urYQvuktJmc6eNUYqSm2, YesvvNI43gUVYPMfqhG4uRO5t6K2]]
[log] returnAbleChunkedList: [[]] before return

In this line:
returnAbleChunkedList.add(midList);
you add a reference to midList to your output list. If your input is longer than 10, you'll end up adding more than one reference to midList to the output list (i.e. you might now have 2). Subsequently, you clear midList so you now have an output list that contains 2 references to a list that you've now cleared, so you end up with a list containing 2 empty lists.
If, instead, you changed this to:
returnAbleChunkedList.add(midList.toList());
you'd add a copy of midList to your output list and your end up with:
[[a, b, c, d, e, f, g, h, i, j], [k]]
as you expected.

The problem is this:
returnAbleChunkedList.add(midList);
midList.clear();
You add the object midlist to the list and then you clear it. So the object you added will be emptied. You have to create a copy or add the elements of the list.
returnAbleChunkedList.add(midList.toList());
// or
returnAbleChunkedList.add(List.of(midList));
// or
returnAbleChunkedList.add([...midList]);

Related

Dart - Map with List as a value

I have this:
List<ForumCategories>? forumCategories;
var mainCats = List<ForumCategories>.empty(growable: true);
var subCats = <int, List<ForumCategories>>{};
Than this is what I do in order to populate it:
for (var i = 0; i < forumCategories!.length; i++) {
if (forumCategories![i].main == 0) {
subCats[forumCategories![i].slave]?.add(forumCategories![i]);
}
}
And than when I do:
var size = subCats.length;
print("SUBCATS: $size");
Output is always: SUBCATS: 0
This does not populate the map. Any idea why ?
because you're trying to add an item to a null List, see here:
if (forumCategories![i].main == 0) {
subCats[forumCategories![i].slave]?.add(forumCategories![i]);
}
subCats[forumCategories![i].slave] does not exist yet in your map, it's like you saying:
null.add(forumCategories![i]);
nothing will happen.
you need to initialize it by an empty List if it's null like this:
if (forumCategories![i].main == 0) {
(subCats[forumCategories![i].slave] ?? []).add(forumCategories![i]) // this will assign an empty list only the first time when it's null, then it adds elements to it.
}
now before adding elements to that list it will find the empty list to add.

Flutter, when cleaning list that already got added to list, the values are gone

I need to sort the elements by their data.
For example:
When I have 4 entries and 2 of them have the same date, the result will be 3 entries in the result list
This is my code:
Future<List<List<MoodData>>> moodData() async {
var result = await database
.ref()
.child("users/")
.child(user!.uid)
.child("moodData")
.once();
List<MoodData> x = [];
List<List<MoodData>> resultdata = [];
result.snapshot.children.forEach((element) {
maxID = int.parse(element.key.toString());
print(element.child("date").value);
if (x.length != 2) {
x.add(MoodData(
id: int.parse(element.key.toString()),
date: element.child("date").value.toString(),
moodValue: double.parse(element.child("y_value").value.toString()),
text: element.child("text").value.toString()));
} else {
resultdata.add(x);
x.clear();
}
});
print(resultdata);
return resultdata;
}
The problem is, that in the result list, all the elemts are empty lists.
What is my code doing wrong?
When you adding x to resultdata it not produces the copy of x, x just becomes an element of resultdata.
Then you have 2 options for accessing x data:
Using given name x
Get it from resultdata by index
So when you call x.clear() after resultdata.add(x) it's the same as calling resultdata.last.clear().
The right solution is adding a copy of x([...x]) to resultdata:
resultdata.add([...x]);
x.clear();

use a for loop to add element in to the java.util.ArrayList,but the list's address of the reference always changing

I have a strange problem when I use a for loop to add element in to the java.util.ArrayList , but the list's address of the reference always changing
Here is the code:
var curntRow: Row = null
var startTime: lang.Long = null
//this is the list
var standTime: util.ArrayList[Row] = new util.ArrayList[Row]()
for (row <- usersCoorOrderByTime) {
if (curntRow == null) {
startTime = row.getAs[lang.Long](2)
} else if (!row.getAs[String](1).equals(curntRow.getAs[String](1))) {
//And I use the method list.add() right here
standTime.add(Row(row.getAs[String](0), row.getAs[String](1), row.getAs[DoubleType](4), row.getAs[DoubleType](5), curntRow.getAs[lang.Long](2) - startTime))
startTime = row.getAs[lang.Long](2)
}
curntRow = row
}
And please see the pic that I debug below:
addr is "7703"
Before get in the loop The list's addr is "7703"
When is get in the loop ,the address changes
change to "11268"
change to "11287"
The most strange things is when it end the loop, the address has changed back to where it was originally declared
change back to "7703"
finally I get an empty ArrayList
I found the error
the parameter of for loop is Dataframe, I should turn to Array or List then make for loop
Try using Mutable ArrayBuffer. Below is a simple example. I hope it helps.
val x = scala.collection.mutable.ArrayBuffer[String]()
x += "2"
x += "4"
println(x)

Print ACSL Annotations with Frama-C script

I am learning how to develop a Frama-C plugin. After reading the Frama-C Developer manual and doing the CFG plugin example, I tried to do a basic script that prints all annotations in a C file. I came up with this:
open Cil_types
class print_annot out = object
inherit Visitor.frama_c_inplace
method vstmt_aux s =
let annots = Annotations.code_annot s in
let anleng = List.length annots in
if anleng <= 0 then Format.fprintf out "Empty List\n"
else
Format.fprintf out "Number of Annotations: %d\n" anleng;
List.iter (fun annot -> Format.fprintf out " -> s%d\n" annot.annot_id) annots;
Cil.DoChildren
end
let run () =
let chan = open_out "annots.out" in
let fmt = Format.formatter_of_out_channel chan in
Visitor.visitFramacFileSameGlobals (new print_annot fmt) (Ast.get());
close_out chan
let () = Db.Main.extend run
It always says the list is empty even when the input file has ACSL annotations and never prints the annotations id. What am I doing wrong?
Edit:
An example with the following code:
/*# requires y >= 0;
# ensures \result >= 0;
*/
int g(int y){
int x=0;
if(y>0){
x=100;
x=x+50;
x=x-100;
}else{
x = x - 150;
x=x-100;
x=x+100;
}
return x;
}
void main(){
int a = g(0);
}
And invoking frama-c with:
$ frama-c -load-script annot_script.ml condi.c
Gives the following output:
Empty List
Empty List
Empty List
Empty List
Empty List
Empty List
Empty List
Empty List
Empty List
Empty List
Empty List
In your example, none of the annotations are attached to a statement. The requires and the ensures are part of a function contract and are attached to the function g, not to any statement of g.
An annotation that would be attached to a statement would for instance be /*# assert x == 150; */ after the line x=x+50;.
If I modify condi.c to insert this assertion, then with the same commandline, I get:
Empty List
Empty List
Empty List
Empty List
Number of Annotations: 1
-> s1
Empty List
Empty List
Empty List
Empty List
Empty List
Empty List
Empty List
It seems that your script is working as expected, for a value of “expected” that corresponds to printing annotations attached to statements.

Comparing consecutive elements in a queue

I have a queue of elements, sorted by date. I need to extract the first n elements, which have the same date and add them to a temporary ArrayList, from which I choose one of them and scrap the others. After that I need to continue doing the same thing for the next n elements of the queue with the same date (extract them to the temp list and so on) until I have no more items in the queue.
// some notes to help you understand the code
PriorityQueue<Results> r, size(4), elementsEqualByTime(1=2,3=4);
List<Comments> c, size(2);
ArrayList temp;
if (c.size() != r.size() && resultIter.hasNext()) {
//first iteration will compare element 0 to itself -> 100% true
ResultObject r2 = resultIter.next();
ResultObject r1 = r2;
while (resultIter.hasNext() && r1.getTime().equals(r2.getTime())) {
temp.add(r1);
//we add the matching elements before we continue
r1 = r2;
temp.add(r1);
if (resultIter.hasNext()) {
//after we add the 2 matching elements we continue
r2 = resultIter.next();
}
}
//use the items in temp
temp.clear();
}
Right now it works for the 1st set of elements, but on the 2nd iteration it adds no elements to the temp ArrayList. I'd appreciate help with this solution, but am also open to different suggestions.
boolean Check (List<Element> elements,Element element)
{
for(Element element1:elements)
if(element1.equals(element))
return true;
return false;
}
void Stuff()
{
// some notes to help you understand the code
PriorityQueue<Element> r = new PriorityQueue<Element>();
List<Element> c;
List<Element> temp = new ArrayList<Element>();
for(Element element:r)
{
if(!Check(temp, element))
{
// do stuff with temp
temp = new ArrayList<Element>();
}
temp.add(element);
}
}
while (commentIter.hasNext()) {
Comment c1 = null;
temp.add(arrayQueue[0]);
for (int i = 1; i < arrayQueue.length; i++) {
if (!arrayQueue[i].getTime().equals(arrayQueue[i - 1].getTime())) {
c1 = commentIter.next();
//do stuff with the results
temp = new HashSet<ResultObject>();
}
temp.add(arrayQueue[i]);
}
if (!temp.isEmpty()) {
c1 = commentIter.next();
//do stuff with the results
}
temp = new HashSet<ResultObject>();
}
That's a tested solution which works.