How to write a function result to instance variable - dart

I have an error in 5 line
The instance member
'generateId' can't be accessed in an initializer. Try replacing the
reference to the instance member with a different expression
what i shoud do to write a function result to instance variable?
import 'dart:math';
class User{
int id = generateId(10); // error i here
String firstName;
String lastName;
String eMail;
String password;
final DateTime regDate = DateTime.now();
User(this.firstName, this.lastName, this.eMail, this.password,){
id = generateId(10);
}
#override
String toString() =>'User: \n$firstName \n$lastName';
int generateId(int count){
int result;
List <int> nums = [];
for (int i = 0; i < count; i++){
nums.add((Random().nextInt(9) + 1).toInt());
}
result = int.parse(nums.join());
return result;
}
}
void main() {
User newUser = User("D", "P", "example#ex.com", "password");
print(newUser);
}

You should make the generateId method static.
The method does not need access to the object, it uses no instance methods or fields, so it can, and should, be declared static.
(It can also be significantly simplified.)
static int generateId(int count){
var result = 0;
var random = Random();
for (var i = 0; i < count; i++) {
result = result * 10 + random.nextInt(9) + 1;
}
return result;
}
Also consider whether you really need all digits to be non-zero, or you just need the first digit to be non-zero. If so, you can do:
final int id = 1000000000 + Random().nextInt(9000000000);
to get a random ten-digit identifier.

Well, since you have only a single constructor and that sets the id anyway, you can basically remove it:
This:
int id = generateId(10); // error i here
becomes:
late int id;
Done.
In case your really, really need that line, you could make the generateId method either a function instead of a class method, or you could make it static. That should work, too.

Related

dart: access function from list

Edit: i know, always call the first element on list, it isnt the point. i want to call numbers[0] func. and it regenerate new int.actually codes are not same which mine, i have a custom class which based on functions with random int and i need to use list of my custom class , so if i use func in list it will be awesome, how can i make new numbers list each time. when app start list regenerated, but i want when i call the list, it will regenerated
i want to print new int for each print but it prints same int , i tried so many thing and i cant figure out
void main{
int ramdomint(){
final _random = new Random();
int _num = _random.nextInt(100);
return _num;
}
List<int> numbers=[ramdomint(),ramdomint(),ramdomint()];
void printNums(){
for(var i=0;i<3;i++){
List<int> newNumbers =new List.from(numbers); //what can i use for this?
print(newNumbers[0]); //edit:i dont want [i], iwant to use ewNumbers[0] for new int for each time
}
}
printNums();
// expected new int for each but same one
}
solution from a friend:
import 'dart:math';
int get ramdomint => Random().nextInt(100);
List<int> get numbers => [ramdomint, ramdomint, ramdomint];
void main() {
for (var i = 0; i < 3; i++) {
print(numbers[0]);
}
}
Do not nest functions. Move ramdomint and printNums outside main function.
Add an empty list of arguments to the main function.
printNums: pass list of numbers as an argument.
printNums: you don't need to copy the list to the newNumbers if you want only to display the content of the list.
printNums: the problem is, you access only first element of the list (with 0 index).
import 'dart:math';
void main() {
List<int> numbers = [ramdomint(), ramdomint(), ramdomint()];
printNums(numbers);
}
int ramdomint() => Random().nextInt(100);
void printNums(List<int> numbers) {
// Easier way:
for (int item in numbers) {
print(item);
}
// Your way:
for (int i = 0; i < numbers.length; i++) {
print(numbers[i]);
}
}
EDIT:
According to #jamesdlin's comment, you can extend list class to randomize unique values in the list:
import 'dart:math';
void main() {
var numbers = <int>[]..randomize();
printNums(numbers);
}
void printNums(List<int> numbers) {
// Easier way:
for (int item in numbers) {
print(item);
}
// Your way:
for (int i = 0; i < numbers.length; i++) {
print(numbers[i]);
}
}
extension on List<int> {
void randomize({
int length = 3,
int maxValue = 100,
}) {
final generator = Random();
for (var i = 0; i < length; i++) {
add(generator.nextInt(maxValue));
}
}
}
The Problem here is that you are creating a list from the numbers list and accessing only the first element.
So it always prints the first element.
import 'dart:math';
void main() {
int ramdomint(){
final _random = new Random();
int _num = _random.nextInt(100);
return _num;
}
List<int> numbers=[ramdomint(),ramdomint(),ramdomint()];
void printNums(){
for(var i=0;i<3;i++){
print(numbers[i]);
}
}
printNums();
}
Don't want newNumbers, because it is already in List.
and the usage of List.from() - Documentation
Hope that works!

Stream Data Calculation In Flux

The following code illustrates a logic I need in a Spring Reactive project:
Inputs:
var period = 3;
int [] inArr = {2, 4, 6, 7, 9, 11, 13, 16, 17, 18, 20, 22 };
Calculation:
var upbond = inArr[0] + period;
var count =0;
List<Integer> result = new ArrayList();
for(int a: inArr){
if(a <= upbond){
count++;
}else{
result.add(count);
count = 1;
upbond += period;
}
}
result.add(count);
System.out.println(Arrays.toString(result.toArray()));
The data source of the sorted integers is the Flux from DB where it shall continually fetch data once a new suitable data is written into the DB. And the result shall be a stream that is sending out to another node through RSocket (by the request-stream communication mode).
After some online searching on Reactor, including some tutorials, I still can't figure out how to write the logic in the Flux fashion. The difficulty I have is that those calculations on data defined outside of the loop.
How shall I approach it in the Reactor?
The scan() variant that lets you use a separately typed accumulator is your friend here.
I'd approach this with a separate State class:
public class State {
private int count;
private Optional<Integer> upbond;
private Optional<Integer> result;
public State() {
this.count = 0;
this.upbond = Optional.empty();
this.result = Optional.empty();
}
public State(int count, int upbond) {
this.count = count;
this.upbond = Optional.of(upbond);
this.result = Optional.empty();
}
public State(int count, int upbond, int result) {
this.count = count;
this.upbond = Optional.of(upbond);
this.result = Optional.of(result);
}
public int getCount() {
return count;
}
public Optional<Integer> getUpbond() {
return upbond;
}
public Optional<Integer> getResult() {
return result;
}
}
...and then use scan() to build up the state element by element:
sourceFlux
.concatWithValues(0)
.scan(new State(), (state, a) ->
a <= state.getUpbond().orElse(a + period) ?
new State(state.getCount() + 1, state.getUpbond().orElse(a + period)) :
new State(1, state.getUpbond().orElse(a + period) + period, state.getCount())
)
.windowUntil(s -> s.getResult().isPresent())
.flatMap(f -> f.reduce((s1, s2) -> s1.getResult().isPresent()?s1:s2).map(s -> s.getResult().orElse(s.getCount() - 1)))
Aside: The concatWithValues() / windowUntil() / flatMap() bits are there to handle the last element - there's probably a cleaner way of achieving that, if I think of it I'll edit the answer.
I think scan is definitely the right tool here, combined with a stateful class, although my approach would be slightly different than Michaels.
Accumulator:
class UpbondAccumulator{
final Integer period;
Integer upbond;
Integer count;
Boolean first;
Queue<Integer> results;
UpbondAccumulator(Integer period){
this.period = period;
this.count = 0;
this.upbond = 0;
this.results = new ConcurrentLinkedQueue<>();
this.first = true;
}
//Logic is inside accumulator, since accumulator is the only the only thing
//that needs it. Allows reuse of accumulator w/o code repetition
public UpbondAccumulator process(Integer in){
//If impossible value
//Add current count to queue and return
//You will have to determine what is impossible
//Since we concat this value on the end of flux
//It will signify the end of processing
//And emit the last count
if(in<0){
results.add(count);
return this;
}
//If first value
//Do stuff outside loop
if(this.first) {
upbond = in + period;
first=false;
}
//Same as your loop
if(in <= upbond)
count++;
else {
results.add(count);
count = 1;
upbond += period;
}
//Return accumulator
//This could be put elsewhere since it isn't
//Immediately obvious that `process` should return
//the object but is simpler for example
return this;
}
public Mono<Integer> getResult() {
//Return mono empty if queue is empty
//Otherwise return queued result
return Mono.justOrEmpty(results.poll());
}
}
Usage:
dbFlux
//Concat with impossible value
.concatWithValues(-1)
//Create accumulator, process value and return
.scan(new UpbondAccumulator(period), UpbondAccumulator::process)
//Get results, note if there are no results, this will be empty
//meaning it isn't passed on in chain
.flatMap(UpbondAccumulator::getResult)
Following comment from Michael here is an immutable approach
Accumulator:
public class UpbondAccumulator{
public static UpbondState process(int period,Integer in,UpbondState previous){
Integer upbond = previous.getUpbond().orElse(in + period);
int count = previous.getCount();
if(in<0) return new UpbondState(upbond, count, count);
if(in <= upbond) return new UpbondState(upbond,count + 1 , null);
return new UpbondState(upbond + period, 1, count);
}
}
State object:
public class UpbondState {
private final Integer upbond;
private final int count;
private final Integer result;
public UpbondState() {
this.count = 0;
this.upbond = null;
this.result = null;
}
public UpbondState(Integer upbond, int count,Integer result) {
this.upbond = upbond;
this.count = count;
this.result = result;
}
public int getCount() { return count; }
public Optional<Integer> getUpbond() { return Optional.ofNullable(upbond); }
public Integer getResult() { return result; }
public boolean hasResult() { return result!=null; }
}
Usage:
dbFlux
.concatWithValues(-1)
.scan(new UpbondState(),
(prev, in) -> UpbondAccumulator.process(period,in,prev))
//Could be switched for Optional, but would mean one more map
//+ I personally think makes logic less clear in this scenario
.filter(UpbondState::hasResult)
.map(UpbondState::getResult)

How to compare objects in Vala?

I am using a Gee.ArrayList with an own class for content. I want to use the "contains" method of the ArrayList, but I really don't know how to set up an equals-method in my class, so ArrayList uses it to find out if the object is in the ArrayList or not.
Example:
class Test : GLib.Object {
public int number;
public Test(int n) {
number = n;
}
public bool equals (Test other) {
if (number == other.number) return true;
return false;
}
}
Then, in another file:
var t = new Gee.ArrayList<Test>();
var n1 = new Test(3);
var n2 = new Test(3);
t.add(n1);
t.contains(n2); // returns false, but I want it to return true
Does anybody know that?
When you create the ArrayList, the constructor takes your equality comparator. You can do:
var t = new Gee.ArrayList<Test>(Test.equals);
and the contains should work as you desire.

Method declaration in java

I have a question regarding this code, you can see in some methods that there are comments with a return, that is because I think I have to use a return method instead of a void method. My teacher told me to transform them to a void class, but isn't a method which modifies field variables suposed to return something? I'm in doubt because sometimes my teacher seems to not know so much about programming or has some doubts so, thank for your help beforehand.
public class ArraysClass {
private int[] array;
private int arrayLength;
public ArraysClass() {
setArrayLength();
array = new int[arrayLength];
}
public int setArrayLength() {
Scanner scanner = new Scanner(System.in);
System.out.println("Enter a number to set the length of the array:");
arrayLength = scanner.nextInt();
System.out.println();
return arrayLength;
}
public void fillArray() {
Scanner scanner = new Scanner(System.in);
for (int i = 0; i < arrayLength; i++) {
System.out.println("Type a number to fill position " + i);
array[i] = scanner.nextInt();
}
// return array;
System.out.println();
}
public void findNumber() {
Scanner scanner = new Scanner(System.in);
int tofind, position;
System.out.println("Enter a number to search it in the array:");
tofind = scanner.nextInt();
position = Arrays.binarySearch(array, tofind);
if (position < 0) {
System.out.println("We did not find your number.");
} else {
System.out.println("The number you typed is in the next position: " + position);
}
System.out.println();
}
public void fillMethod() {
Scanner scanner = new Scanner(System.in);
int tofill;
System.out.println("Enter a number to fill the entire array with:");
tofill = scanner.nextInt();
Arrays.fill(array, tofill);
System.out.println();
//return array;
}
public void Sortmethod() {
Arrays.sort(array);
//return array;
}
private void showArray() {
System.out.println("Showing the array...");
for (int i = 0; i < arrayLength; i++) {
System.out.println(array[i]);
}
System.out.println();
}
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
ArraysClass arrayobj = new ArraysClass();
int choose;
do {
do {
System.out.println("1-Fill the array");
System.out.println("2-Find a number in the array");
System.out.println("3-Fill the entire array with a number");
System.out.println("4-Sort the array");
System.out.println("5-Show the array");
System.out.println("6-Exit");
System.out.println("Which one do you want to use?:");
choose = scanner.nextInt();
} while (choose < 1 && choose > 6);
switch (choose) {
case 1:
arrayobj.fillArray();
break;
case 2:
arrayobj.findNumber();
break;
case 3:
arrayobj.fillMethod();
break;
case 4:
arrayobj.Sortmethod();
break;
case 5:
arrayobj.showArray();
break;
case 6:
break;
}
} while (choose != 6);
}
}
In general, a method should return something if you need value from it. It is an approach used by some programmers to return a boolean even for do-only methods for success or failure or an int, for a status code. I do not follow these approaches. When I implement a method, I always ask myself how would I like to use that method. If I need a value from it, then it will have its type. Otherwise, it will be void. Let us see your methods:
setArrayLength: In general, from this name I would expect that you pass an int to it, representing the length and the method to be void. This is very common for setters, but here you are reading the actual value inside the method which is clearly inferior compared to having an int parameter, as your method will be useless if one wants to set the array length using a value not read from the console.
fillArray: I would expect this to be void, so I agree with its declaration, but again, the reading part should not be here.
findNumber: Should get the number to be found as a parameter and return an int, which represents its index, -1 if not found.
fillMethod: Should be void and should have an int parameter, which represents the value to be used to fill the array.
sortMethod: ok, maybe return the resulting array, but depends on your needs.
showArray: I would expect a PrintStream there, you will not necessarily output to System.out
General mistake: You mix methods with in/out operations to the console, the code is not general enough this way.

How to set values of global variables used in function parameters

I can conveniently change opsCount variable directly from inside the function,
because there is only one of that type of variable.
int opsCount = 0;
int jobXCount = 0;
int jobYCount = 0;
int jobZCount = 0;
void doStats(var jobCount) {
opsCount++;
jobCount++;
}
main() {
doStats(jobXCount);
}
But there are many jobCount variables, so how can I change effectively that variable, which is used in parameter, when function is called?
I think I know what you are asking. Unfortunately, the answer is "you can't do this unless you are willing to wrap your integers". Numbers are immutable objects, you can't change their value. Even though Dart's numbers are objects, and they are passed by reference, their intrinsic value can't be changed.
See also Is there a way to pass a primitive parameter by reference in Dart?
You can wrap the variables, then you can pass them as reference:
class IntRef {
IntRef(this.val);
int val;
#override
String toString() => val.toString();
}
IntRef opsCount = new IntRef(0);
IntRef jobXCount = new IntRef(0);
IntRef jobYCount = new IntRef(0);
IntRef jobZCount = new IntRef(0);
void doStats(var jobCount) {
opsCount.val++;
jobCount.val++;
}
main() {
doStats(jobXCount);
print('opsCount: $opsCount; jobXCount: $jobXCount; jobYCount: $jobYCount; jobZCount: $jobZCount');
}
EDIT
According to Roberts comment ..
With a custom operator this would look like:
class IntRef {
IntRef(this.val);
int val;
#override
String toString() => val.toString();
operator +(int other) {
val += other;
return this;
}
}
void doStats(var jobCount) {
opsCount++;
jobCount++;
}

Resources