Java 8 Sorting Custom Sorting - sorting

class A {
private String name;
private int grade;
private RD rd;
// setters & getters
}
class RD {
private double ef;
private double mf;
private int doe;
// setters & getters
}
Custom Sorting based on 4 different columns.
Grade, in ascending order
ef in descending order
doe in ascending order
mf in descending order
I tried it doing it.
But i am not getting the proper output.
Here is what i did.
class SortingCustom {
public static void main(String[] args) {
List<A> aList = new ArrayList<A>();
Collections.sort(aList, Comparator.comparing(A::getGrade)
.thenComparing((A a, A b) -> {
return Double.compare(b.getRd().getEf(), a.getRd().getEf());
})
.thenComparing((A a, A b) -> {
return Integer.compare(a.getRd().getDoe(), b.getRd().getDoe());
})
.thenComparing((A a, A b) -> {
return Double.compare(b.getRd().getMf(), a.getRd().getMf());
})
);
//This doesnot sort all data.
}
}
Sample Output
Grade EF DOE MF
====== ===== ===== ====
1 0.27 4 0.72
2 0.98 2 0.34
2 0.96 3 0.93
2 0.96 3 0.91
2 0.96 3 0.87
2 0.96 3 0.65
2 0.96 4 0.34
2 0.87 4 0.25
3 0.67 4 0.22
3 0.45 6 0.17

Related

Creating List<Object> inside map

I have string like:
String input = "1 2 20\n"
+ "1 3 50\n"
+ "1 4 40\n"
+ "1 5 30\n"
+ "2 3 20\n"
+ "2 4 40\n"
+ "2 5 30\n"
+ "3 4 50\n"
+ "3 5 60\n"
+ "4 5 70\n";
}
My Nodes Class:
class Nodes{
Integer from;
Integer to;
Integer cost;
}
Corresponding to each String input i want a Nodes object.
SO far I have been able to do like:
List<Nodes> collect = new ArrayList<>();
for loop starts here until the inputs are exhausted.
String[] s = Arrays.stream("1 3 50".split(" ")).toArray(String[]::new);
Nodes nodes = new Nodes(Integer.valueOf(s[0]),Integer.valueOf(s[1]),Integer.valueOf(s[2]));
collect.add(nodes);
for loop ends here
Required output :
List<Nodes>
Is there a way so that I can create a List of Nodes inside stream only like map(h->new Nodes(h[0],h[1],h[2]))and at last collect it using Collectors.toList() so that i have List<Nodes>.
Try this one
List<Nodes> nodes = Arrays.stream(input.split("\\n"))
.map(s->s.split("\\s"))
.map(arr->new Nodes(Integer.valueOf(arr[0]),Integer.valueOf(arr[1]),
Integer.valueOf(arr[2])))
.collect(Collectors.toList());
I would make some modifications to your Nodes class first. Including some error handling in case there is something else than ints in your String. Then stream and collect:
import java.util.List;
import java.util.stream.Collectors;
public class StackOverflowTest {
public static void main(String[] args) {
String input = "1 2 20\n"
+ "1 3 50\n"
+ "1 4 40\n"
+ "1 5 30\n"
+ "2 3 20\n"
+ "2 4 40\n"
+ "2 5 30\n"
+ "3 4 50\n"
+ "3 5 60\n"
+ "4 5 70\n";
List<Nodes> list =
input.lines() // streaming each line
.map(s -> new Nodes(s.split(" "))) // creating Nodes
.collect(Collectors.toList()); // Collecting to List
System.out.println(list);
}
}
class Nodes{
Integer from;
Integer to;
Integer cost;
Nodes(String[] strings) {
this(stringToInts(strings)); // avoid throwing error in constructor
}
Nodes(int[] ints) {
this.from = ints[0];
this.to = ints[1];
this.cost = ints[2];
}
public String toString() {
return "Nodes:from=" + from + ".to=" + to + ".cost=" + cost + "\n";
}
private static int[] stringToInts(String[] strings) {
if (strings.length != 3) throw new AssertionError("String array of wrong size. Must be 3");
int[] ints = new int[strings.length];
for (int i = 0; i < strings.length; i++) {
ints[i] = Integer.parseInt(strings[i]);
}
return ints;
}
}
On reflection the exeption handling can also be achieved just by adding
.map(arr-> {if (arr.length != 3) throw new AssertionError("Array size != 3"); return arr;})
to the Answer by Hadi J
I don't code java but in python there's a function called list() that converts string to lists and maybe there is one on java too.
or maybe use split(", ") and maybe it will work.

Algorithm to produce number series

I am not sure how to attack this problem... I tried many things, and it seems to be that it shouldn't be so difficult, but not getting there...
Is it possible to create a function "series ( _x )", that produces this :
The function for example should be myfunction( 11 ) => 211
The terms become suffix for the next terms. See below picture for more clarity. The boxes with same color gets repeated. So, we could just keep prepending 1 and 2 for previous results.
Code(In java):
public class Solution {
public static void main(String[] args) {
List<String> ans = solve(10);
for(int i=0;i<ans.size();++i) System.out.println(ans.get(i));
}
private static List<String> solve(int terms){
List<String> ans = new ArrayList<>();
String[] digits = new String[]{"1","2"};
ans.add("1");
if(terms == 1) return ans;
ans.add("2");
if(terms == 2) return ans;
List<String> final_result = new ArrayList<>();
final_result.addAll(ans);
terms -= 2;//since 2 numbers are already added
while(terms > 0){
List<String> temp = new ArrayList<>();
for(String s : digits){
for(int j=0;j<ans.size() && terms > 0;++j){
temp.add(s + ans.get(j));
terms--;
}
}
ans = temp;
final_result.addAll(ans);
}
return final_result;
}
}
This hint should help you... It isn't quite binary, but it is close. Let me know if you need any further help
0 -> - -> -
1 -> - -> -
10 -> 0 -> 1
11 -> 1 -> 2
100 -> 00 -> 11
101 -> 01 -> 12
110 -> 10 -> 21
111 -> 11 -> 22
1000 -> 000 -> 111
1001 -> 001 -> 112
1010 -> 010 -> 121
1011 -> 011 -> 122
1100 -> 100 -> 211
1101 -> 101 -> 212
1110 -> 110 -> 221
1111 -> 111 -> 222
Edit: I didn't like the way I ordered the columns, so I swapped 2 and 3
Python approach
First thing that we need to do is produce binary strings
in Python this can be done with bin(number)
However this will return a number in the form 0b101
We can easily strip away the 0b from the beginning though by telling python that we dont want the first two characters, but we want all the rest of them. The code for that is: bin(number)[2:] left side of the : says start two spaces in, and since the right side is blank go to the end
Now we have the binary numbers, but we need to strip away the first number. Luckily we already know how to strip away leading characters so change that line to bin(number)[3:].
All that is left to do now is add one to every position in the number. To do that lets make a new string and add each character from our other string to it after incrementing it by one.
# we already had this
binary = bin(user_in + 1)[3:]
new = ""
for char in binary:
# add to the string the character + 1
new += str(int(char) + 1)
And we are done. That snippet will convert from decimal to whatever this system is. One thing you might notice is that this solution will be offset by one (2 will be 1, 3 will be 2) we can fix this by simply adding one to user input before we begin.
final code with some convenience (a while loop and print statement)
while True:
user_in = int(input("enter number: "))
binary = bin(user_in + 1)[3:]
new = ""
for char in binary:
new += str(int(char) + 1)
print(user_in, "\t->\t", binary, "\t->\t", new)
According to A000055
We should perform 3 steps:
Convert value + 1 to base 2
Remove 1st 1
Add 1 to the rest digits
For instance, for 11 we have
Converting 11 + 1 == 12 to binary: 1100
Removing 1st 1: 100
Adding 1 to the rest digits: 211
So 11 has 211 representation.
C# code:
private static String MyCode(int value) =>
string.Concat(Convert
.ToString(value + 1, 2) // To Binary
.Skip(1) // Skip (Remove) 1st 1
.Select(c => (char)(c + 1))); // Add 1 to the rest digits
Demo:
var result = Enumerable
.Range(1, 22)
.Select(value => $"{MyCode(value),4} : {value,2}");
Console.Write(string.Join(Emvironment.NewLine, result));
Outcome:
1 : 1
2 : 2
11 : 3
12 : 4
21 : 5
22 : 6
111 : 7
112 : 8
121 : 9
122 : 10
211 : 11
212 : 12
221 : 13
222 : 14
1111 : 15
1112 : 16
1121 : 17
1122 : 18
1211 : 19
1212 : 20
1221 : 21
1222 : 22
In VB.NET, showing both the counting in base-3 and OEIS formula ways, with no attempts at optimisation:
Module Module1
Function OEIS_A007931(n As Integer) As Integer
' From https://oeis.org/A007931
Dim m = Math.Floor(Math.Log(n + 1) / Math.Log(2))
Dim x = 0
For j = 0 To m - 1
Dim b = Math.Floor((n + 1 - 2 ^ m) / (2 ^ j))
x += CInt((1 + b Mod 2) * 10 ^ j)
Next
Return x
End Function
Function ToBase3(n As Integer) As String
Dim s = ""
While n > 0
s = (n Mod 3).ToString() & s
n \= 3
End While
Return s
End Function
Function SkipZeros(n As Integer) As String
Dim i = 0
Dim num = 1
Dim s = ""
While i < n
s = ToBase3(num)
If s.IndexOf("0"c) = -1 Then
i += 1
End If
num += 1
End While
Return s
End Function
Sub Main()
Console.WriteLine("A007931 Base3 ITERATION")
For i = 1 To 22
Console.WriteLine(OEIS_A007931(i).ToString().PadLeft(7) & SkipZeros(i).PadLeft(7) & i.ToString().PadLeft(11))
Next
Console.ReadLine()
End Sub
End Module
Outputs:
A007931 Base3 ITERATION
1 1 1
2 2 2
11 11 3
12 12 4
21 21 5
22 22 6
111 111 7
112 112 8
121 121 9
122 122 10
211 211 11
212 212 12
221 221 13
222 222 14
1111 1111 15
1112 1112 16
1121 1121 17
1122 1122 18
1211 1211 19
1212 1212 20
1221 1221 21
1222 1222 22

Reading a file and output selected data

I'm trying to read data and output only selected data from a CSV file(Date, time and S(speed). My program is able to run but it loops in a weird way. Line 1, than Line 1 and 2, than Line 1,2 and 3 and so on and so forth. The final record that is shown in the program is also incorrect(0/3/2016 23:50). Need some guidance to rectify this problem.
Sample data in notepad format below. It contains thousands of line but only pick the last 3 lines to illustrate my problem. Ignore the "Line" below, it's just to tell you which line is in excel format. Line 1 is the header which i ignore, follow by the data.
Line 1:WAST,DP,Dta,Dts,EV,QFE,QFF,QNH,RF,RH,S,SR,ST1,ST2,ST3,ST4,Sx,T
Line 2: 31/03/2016 23:30,11.4,257,11,0,1012.9,1016.4,1016.5,0,63.5,5,13,26.4,25.8,25.6,26.1,7,18.48
Line 3: 31/03/2016 23:40,11.4,250,15,0,1012.9,1016.4,1016.5,0,64.7,5,10,26.4,25.8,25.6,26.1,6,18.19
Line 4:31/03/2016 23:50,11.4,243,5,0,1012.7,1016.2,1016.3,0,65.8,3,11,26.3,25.8,25.6,26.1,5,17.95
Current Output:
31/3/2016 23:30
Speed: 5
31/3/2016 23:30
Speed: 5
31/3/2016 23:40
Speed: 5
31/3/2016 23:30
Speed: 5
31/3/2016 23:40
Speed: 5
31/3/2016 23:50
Speed: 3
31/3/2016 23:30
Speed: 5
31/3/2016 23:40
Speed: 5
31/3/2016 23:50
Speed: 3
0/3/2016 23:50
Speed: 3
Max Speed: 5
Done!
Intended Output
31/3/2016 23:30
Speed: 5
31/3/2016 23:40
Speed: 5
31/3/2016 23:50
Speed: 3
Max Speed: 5
Done!
using namespace std;
typedef struct
{
Date d;
Time t;
float speed;
}
WindLogType;
//declare speed max function
ostream & operator <<(ostream &osObject, const WindLogType & w1);
istream & operator >>(istream &input, WindLogType &w1);
int main()
{
string filename;
ifstream input;
filename = "Data.csv";
input.open(filename.c_str());
input.ignore(500,'\n');
Vector<WindLogType> windlog;
string line,line2, readDay, readMonth, readYear, readHour, readMinute;
float sp;
while(!input.eof())
{
getline(input,readDay,'/');
getline(input,readMonth,'/');
getline(input,readYear,' ');
getline(input,readHour,':');
getline(input,readMinute,',');
int day1 =atoi(readDay.c_str());
int month1=atoi(readMonth.c_str());
int year1=atoi(readYear.c_str());
int hour1=atoi(readHour.c_str());
int minute1=atoi(readMinute.c_str());
float s1;
for(int i = 0;i<10;i++)
{
input>>s1;
input.ignore(50,',');
}
WindLogType T1;//create a record
T1.d.setDate(day1,month1,year1);
T1.t.setTime(hour1,minute1);
T1.speed = s1;
windlog.push_back(T1);//push inside vector
windlog.print();
getline(input,line2,'\n');
}
float maxSpeed;
WindLogType H1;
H1=windlog.at(0);
maxSpeed=H1.speed;
for(int i=0;i<windlog.size();i++)
{
if(windlog.at(i).speed>maxSpeed)
{
maxSpeed=windlog.at(i).speed;
}
}
cout<<"Max Speed: "<<maxSpeed<<endl;
cout<<"Done!"<<endl;
return 0;
}
ostream & operator <<(ostream &osObject, const WindLogType &w1)
{
osObject<<w1.d<<w1.t<<endl<<"Speed: "<<w1.speed;
return osObject;
}
istream &operator >>(istream & input, WindLogType &w1)
{
input>>w1.d>>w1.t>>w1.speed;
return input;
}

How to handle the often-generated messages?

I have the following system:
producer ---> proxy ---> consumer
<good> 10 msg/s
A producer that generates messages - 10 msg/second. A proxy that returns bool value to a consumer depends on how many messages producer generated, if it generate more than 10, proxy returns false.
This is timestamp:
0.1
0.2
0.25
0.26
0.27
0.28
0.29
0.30
0.31
0.32
0.33
0.34
2.0
2.1
2.2
Messages that comes at 0.1, 0.2, 0.25 ... 0.32 they are good and we return true, 0.32 is bad because it's 11th message in 1 second, so we return false.
Here is a protoype:
bool shouldProxyAcceptMessage(float timestamp)
How can I implement this algorithm?
Okay, I adapted the solution based on the OP's comments. The algorithm uses two global variables, nrMessages and startTime, and it initializes startTime to the current time whenever nrMessage==0 (i.e. when it receives the first message); it returns true for the first 10 timestamps that arrived within 1 second. Once it receives a timestamp older than 1 second, it resets nrMessages=0 (so startTime will reinitialize when the next timestamp arrives).
An implicit assumption we're
long nrMessages = 0; // global variable
long startTime = 0;
boolean shouldProxyAcceptMessage(long timestamp) {
if (nrMessages++ == 0) {
startTime = System.currentTimeMillis()();
}
timeDiff = timestamp-startTime;
if (timeDiff > 1000) {
nrMessages = 0;
return false;
} else {
return nrMessages <= 10;
}
}

How to display all number by increment?

i was task to ask a user to enter a number in range from 1 to 15 and after 5 input, i suppose to display all the number that enter by the user.
saying the user enter 2, 3, 4, 5, and 6, this is what i suppose to display:
1 2
1 2 3
1 2 3 4
1 2 3 4 5
1 2 3 4 5 6
package barChartPrinting;
import java.util.Scanner;
public class barChart {
public static void main(String[] args) {
Scanner keyboard = new Scanner(System.in);
int getNumber;
for (int counter = 0; counter < 5; counter++){
System.out.println("Enter a numbers in range of 1 to 15: ");
getNumber = keyboard.nextInt();
while (getNumber < 1 || getNumber > 15){
System.out.println("Invalid number!, please re-enter: ");
getNumber = keyboard.nextInt();
}
}
//end of statement here
}
}

Resources