How to reduce a stream of double properties with add? - javafx

Given I have a stream or list of double properties that should all be bind together with the add operation, what is the right way to do this in JavaFX?
The following doesn't work since DoubleExpression::add returns a DoubleBinding instead of a DoubleProperty.
DoubleBinding value = doubleProperties.stream()
.reduce(doubleProperty, doubleProperty2) -> doubleProperty.add(doubleProperty2)).get();
DoubleBinding value = doubleProperties.stream()
.reduce(DoubleExpression::add).get();
The following works but is a hack that I don't think should be necessary:
DoubleBinding value = doubleProperties.stream()
.map(doubleProperty -> doubleProperty.add(0))
.reduce(DoubleExpression::add)
.get();

The most use able solution for me is using DoubleExpression instead of DoubleProperty or DoubleBinding.
DoubleExpression value = doubleProperties.stream()
.map(DoubleProperty::doubleExpression)
.reduce(DoubleExpression::add)
.get();
I don't actually understand the nuances between these three classes.
If someone knows if this construct does what I probably expect and what the differences are, please feel free to comment or answer.

Related

.Net Core 3 Preview SequenceReader Length Delimited Parsing

I'm trying to use SequenceReader<T> in .Net Core Preview 8 to parse Guacamole Protocol network traffic.
The traffic might look as follows:
5.error,14.some text here,1.0;
This is a single error instruction. There are 3 fields:
OpCode = error
Reason = some text here
Status = 0 (see Status Codes)
The fields are comma delimited (semi-colon terminated), but they also have the length prefixed on each field. I presume that's so that you could parse something like:
5.error,24.some, text, with, commas,1.0;
To produce Reason = some, text, with, commas.
Simple comma delimited parsing is simple enough to do (with or without SequenceReader). However, to utilise the length I've tried the following:
public static bool TryGetNextElement(this ref SerializationContext context, out ReadOnlySequence<byte> element)
{
element = default;
var start = context.Reader.Position;
if (!context.Reader.TryReadTo(out ReadOnlySequence<byte> lengthSlice, Utf8Bytes.Period, advancePastDelimiter: true))
return false;
if (!lengthSlice.TryGetInt(out var length))
return false;
context.Reader.Advance(length);
element = context.Reader.Sequence.Slice(start, context.Reader.Position);
return true;
}
Based on my understanding of the initial proposal, this should work, though also could be simplified I think because some of the methods in the proposal make life a bit easier than that which is available in .Net Core Preview 8.
However, the problem with this code is that the SequenceReader does not seem to Advance as I would expect. It's Position and Consumed properties remain unchanged when advancing, so the element I slice at the end is always an empty sequence.
What do I need to do in order to parse this protocol correctly?
I'm guessing that .Reader here is a property; this is important because SequenceReader<T> is a mutable struct, but every time you access .SomeProperty you are working with an isolated copy of the reader. It is fine to hide it behind a property, but you'd need to make sure you work with a local and then push back when complete, i.e.
var reader = context.Reader;
var start = reader.Position;
if (!reader.TryReadTo(out ReadOnlySequence<byte> lengthSlice,
Utf8Bytes.Period, advancePastDelimiter: true))
return false;
if (!lengthSlice.TryGetInt(out var length))
return false;
reader.Advance(length);
element = reader.Sequence.Slice(start, reader.Position);
context.Reader = reader; // update position
return true;
Note that a nice feature of this is that in the failure cases (return false), you won't have changed the state yet, because you've only been mutating your local standalone clone.
You could also consider a ref-return property for .Reader.

Computed Property that uses itself to compute its value?

I want to have a computed property that tracks that historical max of another property. Both these attributes are a member of an ndb class.
My naive approach was the following:
number = ndb.IntegerProperty(default=0)
highest_ever_number = ndb.ComputedProperty(lambda self: self.highest_ever_number if self.highest_ever_number >= self.number else self.number)
The intent was to set the highest_ever_number to a new number if number ever surpassed highest_ever_number.
This doesn't work because highest_ever_number is initially unset. I cannot set it to a default value using "default=0". Is there a workaround to this?
Thanks
I don't think you can use such conditions inside a Computed Property. This whole functionality can be done within a function, so it doesn't need to be a ComputedProperty. A better alternative to this problem could be to create a class method and call it whenever necessary.
Instead of using a computed property, you should use a normal IntegerProperty but use a _pre_put hook (https://cloud.google.com/appengine/docs/standard/python/ndb/modelclass#hooks) to verify/update highest_ever_number.
I can't test it right now, but this might do the trick:
number = ndb.IntegerProperty(default=0)
highest_ever_number = ndb.ComputedProperty(lambda self: self.highest_ever_number if
self.highest_ever_number and self.highest_ever_number >= self.number else self.number)

Errors in mapping using a stream

I'm currently having troubles figuring out how to use Java 8 streams.
I'm trying to go from lista_dottori (Map<Integer, Doctor>) to a new map patientsPerSp where to every medical specialization (method getSpecialization) I map the number of patients wich have a doctor with this specialization (method getPatients in class Doctor returns a List of that doctor's patients). I can't understand how to use the counting method for this purpose, and I can't seem to find any examples nor explanations for this kind of problems on the internet.
That's what i've written, it does give me error in the counting section:
public Collection<String> countPatientsPerSpecialization(){
patientsPerSp=
lista_dottori.values().stream()
.map(Doctor::getSpecialization)
.collect(groupingBy(Doctor::getSpecialization, counting(Doctor::getPatients.size())))
;
}
Seems that you want to sum the sizes of patients lists. This can be done by summingInt() collector, not counting() (which just counts occurences; doctors in this case). Also mapping seems to be unnecessary here. So you cuold write:
patientsPerSp = lista_dottori.values().stream()
.collect(groupingBy(Doctor::getSpecialization,
summingInt(doctor -> doctor.getPatients().size())));
Note that the results will be incorrect if several doctors have the same patient (this way it will be counted several times). If it's possible in your case, then it would be probably better to make a set of patients:
patientsPerSp = lista_dottori.values().stream()
.collect(groupingBy(Doctor::getSpecialization,
mapping(Doctor::getPatients(), toSet())));
This way you will have a map which maps specialization to the set of patients, so the size of this set will be the count which you want. If you just need the count without set, you can add a final step via collectingAndThen():
patientsPerSp = lista_dottori.values().stream()
.collect(groupingBy(Doctor::getSpecialization,
collectingAndThen(
mapping(Doctor::getPatients(), toSet()),
Set::size)));
I solved the problem avoiding using the streams. That's the solution I used:
public Collection<String> countPatientsPerSpecialization(){
int numSpec = 0;
Map<String, Integer> spec = new HashMap<>();
for(Doctor d : lista_dottori.values()){
if(!spec.containsKey(d.getSpecialization())){
spec.put(d.getSpecialization(), d.getPatients().size());
numSpec++;
}
else{ //cioè se la specializzazione c'è già
spec.replace(d.getSpecialization(), +d.getPatients().size());
}
}
patientsPerSp.add(spec.keySet() + ": " + spec.values());
for(String s : patientsPerSp)
System.out.println(s);
return patientsPerSp;
}
I couldn't seem to be able to solve it using your solutions, although they were very well exposed, sorry.
Thank you anyway for taking the time to answer
Map<String, Integer> patientsPerSpecialization =
doctors.values()
.stream()
.collect(Collectors.groupingBy(Doctor::getSpecialization,
Collectors.summingInt(Doctor::nberOfAssignedPatients)));

What is wrong with this code? why the List does not identify?

what is wrong with this code?
bool claimExists;
string currentClaimControlNo = "700209308399870";
List<string> claimControlNo = new List<string>();
claimControlNo.Add("700209308399870");
if (claimControlNo.Contains(currentClaimControlNo.Substring(0, 14)))
claimExists = true;
else
claimExists = false;
Why the claimControlNo above is coming into false?
Since I know the value exists, how can i tune the code?
It's reporting false because you aren't asking whether the list contains the currentClaimControlNo, you're asking whether it contains a string that is the first fourteen characters of the fifteen-character string currentClaimControlNo.
Try this instead:
claimExists = claimControlNo.Any(ccn => ccn.StartsWith(currentClaimControlNo.Substring(0,14)));
Your count is wrong. There are 15 characters. Your substring is cutting off the last 0 which fails the condition.
Because you're shaving off the last digit in your substring.
if you change the line
if (claimControlNo.Contains(currentClaimControlNo.Substring(0, 14)))
to
if (claimControlNo.Contains(currentClaimControlNo.Substring(0, 15)))
it works.
Because contains on a list looks for the whole item, not a substring:
currentClaimControlNo.Substring(0, 14)
"70020930839987"
Is not the same as
700209308399870
You're missing a digit, hence why your list search is failing.
I think you are trying to find something in the list that contains that substring. Don't use the lists contain method. If you are trying to find something in the list that has the subset do this
claimExists = claimControlNo.Any(item => item.Contains(currentClaimControlNo.Substring(0, 14)))
This goes through each item in claimControlNo and each item can then check if it contains the substring.
Why do it this way? The Contains method on a string
Returns a value indicating whether the specified System.String object occurs within this string.
Which is what you want.
Contains on a list, however
Determines whether an element is in the System.Collections.Generic.List.
They aren't the same, hence your confusion
Do you really need this explaining?
You are calling Substring for 14 characters when the string is of length 15. Then you are checking if your list (which only has one item of length 15) contains an item of length 14. It doesn;t event need to check the value, the length is enough to determine it is not a match.
The solution of course is to not do the Substring, it makes not sense.
Which would look like this:
if (claimControlNo.Contains(currentClaimControlNo))
claimExists = true;
else
claimExists = false;
Then again, perhaps you know you are trimming the search, and are in fact looking for anything that has a partial match within the list?
If this is the case, then you can simply loop the list and do a Contains on each item. Something like this:
bool claimExists = false;
string searchString = currentClaimControlNo.Substring(0, 14);
foreach(var s in claimControlNo)
{
if(s.Contains(searchString))
{
claimExists = true;
break;
}
}
Or use some slightly complex (certainly more complex then I can remember off the top of my head) LINQ query. Quick guess (it's probably right to be fair, I am pretty freaking awesome):
bool claimExists = claimControlNo.Any(x => x.Contains(searchString));
Check it:
// str will be equal to 70020930839987
var str = currentClaimControlNo.Substring(0, 14);
List<string> claimControlNo = new List<string>();
claimControlNo.Add("700209308399870");
The value str isn't contained in the list.

What's the difference manipulating display object position?

I have 2 possibilities. It looks like these are the same (or I'm wrong). Which is better and why?
var quest1:DisplayObject = FrameCanvas.baseCanvas.addChild(app.questionmark1); //
quest1.x = posX; //
quest1.y = posY; //
or
app.questionmark1.x = posX;
app.questionmark1.y = posY;
In the first example quest1 is a reference to app.questionmark1 which you are adding to FrameCanvas.baseCanvas and then updating its x and y.
In the second example you are directly setting the x and y on app.questionmark1.
Both work to update app.questionmark1's x and y properties, but in the second example app.questionmark1 may not be on the stage unless you added it somewhere else in the code.
The second example is better because there's really not a reason to store a reference to app.questionmark1 as quest1 as you already can access it by app.questionmark1.

Resources