Need: To filter out data in list - 1 based on the values present in list - 2 with multiple criteria i.e. combination of Date & Order Number
Issue: Able to filter based on 1 criteria. But when I try adding another filter condition it treats it as 2 separate & not as combination. Unable to figure out how to make it as a combination.
Hope issue faced is clear.
Research: I referred to my earlier query on similar need - Link1 . Also checked - Link2
List 1: (All Orders)
[Date | OrderNumber | Time | Company | Rate ]
[2014-10-01 | 12345 | 10:00:01 | CompA | 1000]
[2015-03-01 | 23456 | 08:00:01 | CompA | 2200]
[2016-08-01 | 34567 | 09:00:01 | CompA | 3300]
[2017-09-01 | 12345 | 11:00:01 | CompA | 4400]
[2017-09-01 | 98765 | 12:00:01 | CompA | 7400]
List 2: (Completed Orders)
[Date | OrderNumber | Time]
[2014-10-01 | 12345 | 10:00:01]
[2015-03-01 | 23456 | 08:00:01]
[2016-08-01 | 34567 | 09:00:01]
[2017-09-01 | 98765 | 12:00:01]
Expected O/p after filter :
[Date | OrderNumber | Time | Company | Rate]
[2017-09-01 | 12345 | 11:00:01 | CompA | 4400]
Code:
// Data extracted from MySQL database
// List 1: All Orders
List<ModelAllOrders> listOrders = getDataFromDatabase.getTable1();
// List 2: Completed Orders
List<ModelCompletedOrders> listCompletedOrders = getDataFromDatabase.getTable2();
// Filter with 1 criteria works
Set<Integer> setOrderNumbers = listCompletedOrders.stream().map(ModelCompletedOrders::getOrderNumber).collect(Collectors.toSet());
listOrders = listOrders.stream().filter(p -> !setOrderNumbers.contains(p.getOrderNumber()).collect(Collectors.toList());
// Below not working as expected when trying to combinational filter
Set<LocalDate> setDates = listCompletedOrders.stream().map(ModelCompletedOrders::getDate).collect(Collectors.toSet());
listOrders = listOrders.stream().filter(p -> !setDates.contains(p.getDate()) && !setOrderNumbers.contains(p.getOrderNumber()))
.collect(Collectors.toList());
You've asked for logic that will do this:
The combination of Date & Order Number is unique. I need to check if that unique combination is present in List-2, if yes then filter out, if not then output should contain that row.
Stream::filter() will return a subset of the stream where the filter predicate returns true (i.e. it filters out those objects in the stream where the predicate is false).
listOrders = listOrders.stream().filter(p -> !setDates.contains(p.getDate()) && !setOrderNumbers.contains(p.getOrderNumber()))
.collect(Collectors.toList());
Your code expression here says "show me orders where the order's date does not appear in the list of prior orders AND where the order's order number does not appear in the list of prior orders". Your logical expression is wrong (you're getting confused between what in electronics would be called positive vs negative logic).
You want either:
listOrders = listOrders.stream().filter(p -> !(setDates.contains(p.getDate()) && setOrderNumbers.contains(p.getOrderNumber())))
.collect(Collectors.toList());
"show me orders where both the order's date and order's id are not
present in the list of prior orders"
or:
listOrders = listOrders.stream().filter(p -> !setDates.contains(p.getDate()) || !setOrderNumbers.contains(p.getOrderNumber()))
.collect(Collectors.toList());
"show me orders where either the order's date has not been seen before
OR the order's id has not been seen before"
I've a lot of tuples with this kind of format:
(1,200,a)
(2,300,a)
(1,300,b)
(2,400,a)
(2,500,b)
(3,200,a)
(3,400,b)
(1,500,a)
(2,400,b)
(3,500,a)
(1,200,b)
My job is to sort in firt time the tuple for the first integer, and then doing the average of the value in the second element of the tuple for each element of the third element of the tuple.
So, the result should be this:
(1,350,a),
(1,250,b),
(2,350,a),
(2,450,b),
(3,350,a),
(3,400,b).
What kind of best practice do you reccomend in this case?
I've tried to do MaptoPair and then groupbykey for the first element of the tuple. Then another MapTopPair and groupbykey for the third element and then reducebykey, but it doesn't work and i don't know why. I don't think i've used the best practice for resolving this type of job.
This is a sketch of my solution
Just use Dataset API. Here in Scala, but Java will be almost identical:
val rdd = sc.parallelize(Seq(
(1,200,"a"), (2,300,"a"), (1,300,"b"), (2,400,"a"), (2,500,"b"),
(3,200,"a"), (3,400,"b"), (1,500,"a"), (2,400,"b"), (3,500,"a"),
(1,200,"b")
))
val df = rdd.toDF("k1", "v", "k2")
df.groupBy("k1", "k2").mean("v").orderBy("k1", "k2").show
+---+---+------+
| k1| k2|avg(v)|
+---+---+------+
| 1| a| 350.0|
| 1| b| 250.0|
| 2| a| 350.0|
| 2| b| 450.0|
| 3| a| 350.0|
| 3| b| 400.0|
+---+---+------+
With RDD map first to have composite key:
rdd
.map(x => ((x._1, x._3), (x._2, 1.0)))
.reduceByKey((x, y) => (x._1 + y._1, x._2 + y._2))
.mapValues(x => x._1 / x._2)
.take(6).foreach(println)
((2,a),350.0)
((3,b),400.0)
((1,b),250.0)
((1,a),350.0)
((3,a),350.0)
((2,b),450.0)
Let's assume a have an index with multiple fields created from #Indexed entities:
----------------------------------
| FieldA | FiedlB | FieldC | ... |
----------------------------------
| AX | BX | other | ... |
----------------------------------
| AZ | BZ | value | ... |
----------------------------------
Would it be possible to construct a facet aggregating values from two fields?
For example - A_&_B:
AX
AZ
BX
BZ
Any other options possible?
I think your best bet is to define a method aggregating the values of both fields and annotate this method to index it as a facet.
Something like:
#Field(bridge = #FieldBridge(impl = CollectionOfStringsFieldBridge.class), analyze = Analyze.NO)
#Facet
public List<String> getAggregatedField() {
return yourAggregatedValue;
}
With CollectionOfStringsFieldBridge being something like: https://github.com/hibernate/hibernate-search/blob/master/orm/src/test/java/org/hibernate/search/test/embedded/fieldoncollection/CollectionOfStringsFieldBridge.java
It's better than aggregating the facet values returned by Lucene manually.
1 public class TestWin{
2 public static void main(String[] args){
3 int n;
4 hexagon[][] board;
5
6 n = 4;
7 board = new hexagon[n][n];
8 board[0][0].value = 'R';
Hi. javac doesn't like what I did on line 8. Does anyone know why?
It's been a while since I've so much as looked at Java, but have you tried doing this first?
board[0][0] = new hexagon(); // or whatever its constructor is
Spot on kwatford. All you have done with line 7 is to tell java to create space for n*n Hexagon objects in a 2 dimensional array.
You will still need to call new for each of these Hexagons
Essentially, you need to replace line 7 with something like:
board = new Hexagon[n][n];
for(int i=0; i<n; i++)
for(int j=0; j<n; j++)
board[i][j] = new Hexagon();
Short Answer:
As kwatford said what you need to do is this:
board[0][0] = new hexagon(); // or whatever its constructor is
Longer Explanation:
Just to expand further. Your 2D array is; an array of pointers (or references in Java). This is what one row of the array will look like immediately after this call board = new hexagon[n][n];:
0 1 2 3 4 5 // column index, row index = 0
-------------------------------------------
| | | | | | | | | | // value
--- | ----- | ----- | ---------------------
| | | ...
| | |
| | |
| | |
| | v
| | Null
| v
| Null
v
Null (This means that it points to nothing)
You tried:
board[0][0].value = 'R';
which is the same as this:
null.value = 'R';
You have initialized your array using this line:
board = new Hexagon[n][n];
But you still need to initialize the elements in your array. This would initialize the first three:
board[0][0] = new hexagon(); // or whatever its constructor is
board[1][0] = new hexagon(); // or whatever its constructor is
board[2][0] = new hexagon(); // or whatever its constructor is
Which would result in an array that looks like this:
0 1 2 3 4 5 // column index, row index = 0
-------------------------------------------
| | | | | | | | | | // value
--- | ----- | ----- | ---------------------
| | |
| | |
| | |
| | |
| | v
| | An instance of type Hexigoon (what you get when you type new Hexigon)
| v
| An instance of type Hexigon (what you get when you type new Hexigon)
v
An instance of type Hexigon (what you get when you type new Hexigon)
I remember banging my head on the table with this exact problem two years ago. I love stackoverflow
To expand on what kwatford said, initializing an array in java gives you nulls if the array type is an object. If you had a raw array, such as an array of doubles, you would start with 0 as the entry for each element of the array.
I'm retrieving data from a table in a database and add the whole row to a TreeMap.
I'm using the following code:
ArrayList<String> listaValores = new ArrayList();
TreeMap<Integer, ArrayList> tmValores = new TreeMap<>();
(...)
while (rs.next())
{
listaValores.clear();
for(int i=2; i<=ncolunas; i++)
{
listaValores.add(rs.getString(i));
}
tmValores.put(rs.getInt(1), listaValores);
}
My TreeMap keys are inserted fine but the values are always repeated as the values from the last line as a result from the SELECT * FROM Table query.
So if my table is:
id | name | last name |
1 | joe | lewis |
2 | mark | spencer |
3 | mike | carter |
4 | duke | melvin |
My TreeMap contains:
1=> duke, melvin
2=> duke, melvin
3=> duke, melvin
4=> duke, melvin
Instead of (as I wanted)
1=> joe, lewis
2=> mark, spencer
3=> mike, carter
4=> duke melvin
Can anyone point me out where is the problem?
I believe you have to reassign the value of listaValores.
Simply change
listaValores.clear();
to
listaValores = new ArrayList<String>();
Objects in Java are passed around as references, so you are in fact adding the same list for all the keys in your map.
Since you clear it at every step and then add some values to it, it will contain just the last row, after the while loop has finished.
What you really want to do is to create an instance of ArrayList for every row and add that to your map, instead of clearing the values in the old one:
while (rs.next())
{
listaValores = new ArrayList<String>();
for(int i = 2; i <= ncolunas; i++)
{
listaValores.add(rs.getString(i));
}
tmValores.put(rs.getInt(1), listaValores);
}