class CustomStack<T> {
final _list = <T>[];
void push(T value) => _list.add(value);
T pop() => _list.removeLast();
T get top => _list.last;
bool get isEmpty => _list.isEmpty;
bool get isNotEmpty => _list.isNotEmpty;
int get length => _list.length;
#override
String toString() => _list.toString();
}
void main() {
CustomStack<String> plates = CustomStack();
//Add plates into the stack
plates.push("Plate1");
plates.push("Plate2");
plates.push("Plate3");
plates.push("Plate Extra");
print(plates);
print(plates[plates.length-1]);
}
I get an error in the last line "The operator '[]' isn't defined for the type 'CustomStack'."
How can I control the index in the stack.
I want to print only "Plate Extra" on the screen.
There is no need to use that structure plates[plates.length-1] if getting the last element is possible with the built function. If you want to get the last item in Custom Stack, you can define a function in your Custom Stack.
T get peek => _list.last;
Related
https://dartpad.dev/?
import 'package:starter/stack.dart';
void main() {
print (calculation("(2+2*6"));
}
calculation(expression){
var tokens = expression.split(" ");
Stack values = Stack();
Stack ops = Stack();
}
note that if I remove the import (first line) I get this error message "The function 'Stack' isn't defined."
and when I add the import the error message is "Unsupported import(s): (package:starter/stack.dart)".
Stack is not built in the dart. But we can make a generic class with its methods(get, push, pop) implementation using list.
class CustomStack<T> {
final _list = <T>[];
void push(T value) => _list.add(value);
T pop() => _list.removeLast();
T get top => _list.last;
bool get isEmpty => _list.isEmpty;
bool get isNotEmpty => _list.isNotEmpty;
#override
String toString() => _list.toString();
}
Just put the above class somewhere in the project lib directory.
And use it like.
CustomStack<String> plates = CustomStack();
//Add plates into the stack
plates.push("Plate1");
plates.push("Plate2");
plates.push("Plate3");
// delete the top plate
plates.pop();
I'm very surprised after this issue. First, inform all things I have used in my project.
I have used Getx in my project. I have called the API using the Getx controller file.
Below code used in getx controller file. "PLTimeSlotModel" is model and. it has two params (name, isselect).
var futureTimeSlot_PL_C_D = Future.value(<PLTimeSlotModel>[]).obs;
callTimeSlotAPI() async {
futureTimeSlot_PL_C_D.value = FetchTimeSlotList();
}
Future<List<PLTimeSlotModel>> FetchTimeSlotList() async {
// Fetching data with API calling
}
Screen A:
List<PLTimeSlotModel> listA = [];
List<PLTimeSlotModel> listB = [];
#override
void initState() {
super.initState();
_plController.callTimeSlotAPI();
}
Another method is to create two lists using the future list:
List<PLTimeSlotModel> temp1 = await _plController.futureTimeSlot_PL_C_D.value;
temp1.forEach((element) {
listA.add(element);
listB.add(element);
});
onclick:
for(int i =0;i<listA.length;i++){
listA[i].isselect = false;
print(listA[i].isselect);
print(listB[i].isselect);
}
Now the issue is I have changed/updated the only "listA" value, So why automatically set the same value to "listB"? The two list is based on the one list.
A List in Dart contains references objects, not the objects themselves. So what you are doing is copying references to objects into two lists. But since they are pointing at the same objects, you will see any modification in one list also happen in the other list. You need to copy each PLTimeSlotModel object and put the copy into your new list.
One way to copy objects is to create an constructor which takes an object of the same type and creates a new object based on this first object. So something like this:
class Person {
String name;
Person(this.name);
Person.fromPerson(Person other) : this(other.name);
#override
String toString() => 'Person($name)';
}
void main() {
final persons = [
Person('Adam'),
Person('Bob'),
];
// Make new list based on persons
final otherPersonList = [
...persons.map((person) => Person.fromPerson(person))
];
otherPersonList[0].name = 'Carl';
print(persons); // [Person(Adam), Person(Bob)]
print(otherPersonList); // [Person(Carl), Person(Bob)]
}
I've got a global list like this:
var data = [1,2,3];
I will add more elements to it, and each time I do I want something else to be notified - I need a stream and listener. So can I make a stream and tell it to run sink.add anytime the list mutates?
var stream = Stream.fromIterable(data);
stream.listen((item) => print(item));
> 1
> 2
> 3
data.add(4);
> Uncaught Error: Concurrent modification during iteration
data.remove(3);
> Uncaught Error: Concurrent modification during iteration
Oh no. What can I do to make this work?
This might help:
import 'dart:async';
class ObservableList<T> {
final _list = <T>[];
final _itemAddedStreamController = StreamController<T>();
final _listStreamController = StreamController<List<T>>();
Stream get itemAddedStream => _itemAddedStreamController.stream;
Stream get listStream => _listStreamController.stream;
void add(T value) {
_list.add(value);
_itemAddedStreamController.add(value);
_listStreamController.add(_list);
}
void dispose() {
_listStreamController.close();
_itemAddedStreamController.close();
}
}
void main() {
final observableList = ObservableList<int>();
observableList.itemAddedStream.listen((value) => print(value));
observableList.add(1);
observableList.add(2);
observableList.add(3);
observableList.add(4);
}
I'm looking at some Flutter code that looks like this :
try {
return Right(_doSomethingAndReturnSingleValue());
} on CustomException {
return Left(CustomException());
}
Left and Right are from the core either.dart package, this is the code :
class Left<L, R> extends Either<L, R> {
final L _l;
const Left(this._l);
L get value => _l;
#override B fold<B>(B ifLeft(L l), B ifRight(R r)) => ifLeft(_l);
#override bool operator ==(other) => other is Left && other._l == _l;
#override int get hashCode => _l.hashCode;
}
class Right<L, R> extends Either<L, R> {
final R _r;
const Right(this._r);
R get value => _r;
#override B fold<B>(B ifLeft(L l), B ifRight(R r)) => ifRight(_r);
#override bool operator ==(other) => other is Right && other._r == _r;
#override int get hashCode => _r.hashCode;
}
I'm really struggling to make any sense of what this logic is supposed to do.
Can anyone help me understand what Left() and Right() are for in Dart ?
Left and Right are two generic classes inherited from the same parent, which does almost same thing. The major difference is in the fold method implementation. The left class call the ifLeft callback and right class call the ifRight callback.
For example:
Either<CustomException, String> getSomething() {
try {
return Right(_doSomethingAndReturnSingleValue());
} on CustomException {
return Left(CustomException());
}
}
No matter what happens the above function will return either an object of Either with CustomException (Means Left) or an object of Either with String (Means Right).
Now if you use the function like:
final eitherData = getSomething();
You will be getting an either object (Object of Left or Right). Instead of checking whether that eitherData is of type Left or Right, you can call the fold method on that object like below:
eitherData.fold<Widget>(
(err) => Text('Error Happened: $err'), // ifLeft callback
(data) => Text('Got data: $data'), // ifRight callback
)
As I mentioned earlier based on the object type the corresponding callback will get triggered and you can gracefully handle the success and error cases without writing any if else statements or type checks.
Hello I want to add some value to my list. I have already googled for solutions but I can't see any other solutions besides initializing the list which I did.
When I try to add an item to my AutomaticDateList class I get the error:
The method 'add' was called on null.
Receiver: null
Tried calling: add(Instance of 'AutomaticDate')
Here is the class with the list in it.
class AutomaticDateList with ChangeNotifier {
List<AutomaticDate> items = []; // here I inialize
AutomaticDateList({this.items});
void addToList(AutomaticDate automaticDate) {
items.add(automaticDate);
notifyListeners();
}
List<AutomaticDate> get getItems => items;
}
This is the item I want to add to the list.
class AutomaticDate with ChangeNotifier {
String date;
String enterDate;
String leaveDate;
String place;
AutomaticDate({this.date, this.enterDate, this.leaveDate, this.place});
Here I call the method using the provider inside a page widget
void onGeofenceStatusChanged(Geofence geofence, GeofenceRadius geofenceRadius,
GeofenceStatus geofenceStatus) {
geofenceController.sink.add(geofence);
AutomaticDate automaticDateData = AutomaticDate();
automaticDateData.place = geofence.id;
automaticDateData.date = DateFormat("dd-mm-yyyy").format(DateTime.now());
if (geofenceStatus == GeofenceStatus.ENTER) {
widget.enterDate = DateFormat("HH:mm:ss").format(DateTime.now());
} else {
automaticDateData.leaveDate =
DateFormat("HH:mm:ss").format(DateTime.now());
automaticDateData.enterDate = widget.enterDate;
widget.list.add(automaticDateData);
WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
AutomaticDateList automaticDateList =
Provider.of<AutomaticDateList>(context, listen: false);
automaticDateList.items.add(automaticDateData); // Here I add the data and get error "add was called on null"
print(automaticDateList.getItems);
});
}
}
The problem is in the initialization:
List<AutomaticDate> items = []; // here I inialize
AutomaticDateList({this.items});
You set a default value, but you are using the "auto-assign" sintax in the constructor, saying that items passing in the parameters are going to be assigned in the items property of the class.
You are instantiating the class using this code:
AutomaticDate automaticDateData = AutomaticDate();
So, you are passing "null" implicitly as parameter, then items [] got replaced with null value.
Just change the code to:
List<AutomaticDate> item;
AutomaticDateList({this.items = []}); // Default value