Set a sequential index within each subgroup of a List using Java 8 forEach or Stream API - foreach

I have an already sorted list of objects, and need to perform a "group by" and assign a sequence number to each object in the group.
[Essentially, I am trying to mimic the effect of a sql window function such as "seq = row_number() over (partition by cust_id)"]
Right now, I am achieving this using the below code, but would like to learn if there is a different way to do it using Java 8 features like stream() or forEach(). Thanks for the help.
int count = 0;
String prev_cust_id = "";
// OrdersList is already sorted by cust_id
for (Order o : orderList) {
// reset index for each new group
if (!o.cust_id.equals(prev_cust_id))
count = 0;
o.seq = ++count;
prev_cust_id = o.cust_id;
}
Update: I was also able to achieve the same with below code, but it is less readable and seems more inefficient. Is there is a better way.
orderList.get(0).seq = 1;
IntStream.range(1, orderList.size())
.forEach(i -> orderList.get(i).seq = orderList.get(i).cust_id.equals(orderList.get(i-1).cust_id) ? OrdersList.get(i-1).seq + 1 : 1);

Related

Google sheets QUERY function for joined cells

for example, I have the next table. And I want to query all values which have the first cell "Computer". I have tried QUERY formula "QUERY(A1,B3;"select B where A = 'Computer'")" but it returns only the first B value - Keyboard.
Is it possible to return all values? Thanks.
I understand that you want to read a table composed of different pieces like the one that you posted, and if a match is found on the left column the script will need to return the contents of the right column. If my assumption is incorrect, please forgive me. An example initial table can look like this one:
In the example we will return the rows that contain PRAESENT in the first column. In that case, you can use the following Apps Script:
function so61913445() {
var sheet = SpreadsheetApp.getActive().getActiveSheet();
var data = sheet.getDataRange().getValues();
var matchData = [];
var indexColumn = 0; // Column A
var targetIndex = "PRAESENT";
for (var r = 0; r < data.length; r++) {
for (var c = 0; c < data[0].length; c++) {
if (c == indexColumn && data[r][c] == targetIndex) {
matchData.push(sheet.getRange(r + 1, c + 2, 3, 1).getValues());
}
}
}
for (var r = 0; r < matchData.length; r++) {
for (var c = 0; c < matchData[0].length; c++) {
sheet.appendRow(matchData[r][c]);
}
}
}
In the code, the first step is to declare some variables to read the sheet (using the methods SpreadsheetApp.getActive() and Spreadsheet.getActiveSheet()), the data (with Sheet.getRange() and Range.getValues() methods) and some settings like the target word to match. After that, the code iterates over the data and, if the target word is found, the code will add the contents of the right column into the final array. Finally, the code will repeat the iteration to write the data just under the table using Sheet.appendRow(). The final result will look like this:
Please, ask me any question if you still need some help.

I can not upload data to a VirtualStringTree

I have a form with a TPageControl that has two tabs. In each of them there is a TVirtualStringTree and I have defined these two structures:
typedef struct tagTTreeMun
{
AnsiString Municipio;
int Padron;
int Censo;
double Relacion;
int Codigo;
} TTreeMun, *PTreeMun;
typedef struct tagTTreePro
{
AnsiString Proceso;
int Padron;
int Censo;
double Relacion;
int Codigo;
}TTreePro, *PTreePro;
I know: they are almost the same; then I explain it. The first one is loaded from four nested querys and it does it without any problem, but the second one ... There's no way!
To load this second I need two querys:
SELECT DISTINCT Date FROM Elections ORDER BY Date DESC
that field Date contains only the year and runs without any problem.
SELECT A.Codigo, B.Name, SUM (C.Padron) Padron, SUM (C.Censo) Census, A.Closed
FROM Elections A, Process B, HisElec C
WHERE A.CodPrv = (SELECT Literal FROM Installation WHERE Label = 'Province')
AND A.CodPrv = B.CodPrv AND B.Codigo = A.Process AND A.Closed = 1
AND A.CodPrv = C.CodPrv AND A.Codigo = C.Election
AND A. Date =: Date
GROUP BY 1, 2, 5
UNION
SELECT A.Codigo, B.Name, SUM (C.Padron) Padron,
(SELECT SUM (Census) FROM Tables WHERE CodPrv = (SELECT Literal FROM Installation WHERE Label = 'Province')) Census,
A.Closed
FROM Elections A, Process B, Dl01 C
WHERE A.CodPrv = (SELECT Literal FROM Installation WHERE Label = 'Province')
AND A.CodPrv = B.CodPrv AND A.Process = B.Code AND A.Closed = 0
AND A. Date =: Date
GROUP BY 1, 2, 5
ORDER BY 1 DESC, 3
It also runs without problems or errors. The problem comes when trying to pass that data to the corresponding TVirtualStringTree.
PTreePro DatPro;
PVirtualNode Node1, Node2, Node3, Node4;
LisPro->NodeDataSize = sizeof (TTreePro);
LisPro->BeginUpdate ();
LisPro->Clear ();
for (;! qTemp1->Eof; qTemp1->Next ())
{
Node1 = LisPro->AddChild (NULL);
DatPro = (PTreePro) LisPro->GetNodeData (Node1);
DatPro->Process = IntToStr(qTemp1->FieldByName ("Date")->AsInteger);
qTemp2->Close ();
qTemp2->ParamByName ("Date")->AsInteger = qTemp1->FieldByName("Date")->AsInteger;
qTemp2->Open ();
for (;! qTemp1->Eof; qTemp1->Next())
{
Node2 = LisPro->AddChild(Node1);
DatPro = (PTreePro)LisPro->GetNodeData(Node2);
DatPro->Process = qTemp1->FieldByName("Name")
[...]
}
}
When trying to create that Node1 in this query, the lines Node1 = ... and DatPro = (PTreePro) ... are executed without major problem, except that Node1, after running the AddChild, has a NULL value and therefore, from then on, it can only give an error because when trying to give value to Process, it automatically gives an execution error.
I have tried putting the load of each of the trees in a different function, by isolating code; I have tried with the same structure (in the end they are identical) or as in the example with two structures, to change the order of execution. For more tests that I have done I am not able to load both trees, in LisPro I ALWAYS do the same to me.

DynamoDB: How to use a filter expression on ios (single column with multiple value)?

I am new in Amazon Web Services. I want to apply expressionAttributeValues filter : value #"3" && :value #"1".
How can I do it?
AWSDynamoDBQueryExpression *queryExpression = [AWSDynamoDBQueryExpression new];
queryExpression.exclusiveStartKey = self.queryStartKey;
queryExpression.limit = #500;
queryExpression.indexName = #"st-lud-index";
if( addedDate > 0 )
{
queryExpression.keyConditionExpression = #"st = :value AND lud > :rangeVal";
queryExpression.expressionAttributeValues = #{#":value":#3,#":rangeVal":[NSNumber numberWithDouble:addedDate]};
}
else
{
queryExpression.keyConditionExpression = #"st = :value";
queryExpression.expressionAttributeValues = #{#":value":#3};
}
You can find instructions on how to do that in the Perform a Query section of the following document:
https://docs.aws.amazon.com/aws-mobile/latest/developerguide/add-aws-mobile-nosql-database.html#add-aws-mobile-nosql-database-crud-read
Thanks,
Rohan
Using keyConditionExpression you can query with only one value for the partition key at a time. Assuming st is your partition key, if you need to get two items one with st=3 and another with st=1, you will need to make two separate requests.
However, lud (assuming its your sort key) can use a comparison operator such as <= X or BETWEEN X and Y etc.
Another way to do this is using a scan which will return all items in the table or index. You can use filterExpression to only return those items with st=3 and st=1. Scan is expensive operation so better to call query twice.

I want to union together four queries and set this to be the repeater's data source

Based on user design I have to union together four queries and put them in a repeater.
var qryIssuer = from l in dbRRSP.LOA
join lrb in dbRRSP.LOAOrReferredBy on l.LOAOrReferredById equals lrb.LoaOrReferredById
join lat in dbRRSP.LOAAccessType on l.LOAAccessTypeId equals lat.LOAAccessTypeId
join iss in dbRRSP.Issuer on l.IssuerId equals iss.IssuerId
where
l.PersonId == personId
select new
{
LOAOrReferredByDescription = lrb.LoaOrReferredByDescription,
lat.LOAAccessTypeDescription,
PersonType = "Issuer",
LOAName = iss.CompanyName,
l.DateAdded
};
var qryEMD = from l in dbRRSP.LOA
join lrb in dbRRSP.LOAOrReferredBy on l.LOAOrReferredById equals lrb.LoaOrReferredById
join lat in dbRRSP.LOAAccessType on l.LOAAccessTypeId equals lat.LOAAccessTypeId
join emd in dbRRSP.Agent on l.AgentId equals emd.AgentId
where
l.PersonId == personId
select new
{
LOAOrReferredByDescription = lrb.LoaOrReferredByDescription,
lat.LOAAccessTypeDescription,
PersonType = "EMD",
LOAName = emd.CompanyName,
l.DateAdded
};
var qryEmdRep = from l in dbRRSP.LOA
join lrb in dbRRSP.LOAOrReferredBy on l.LOAOrReferredById equals lrb.LoaOrReferredById
join lat in dbRRSP.LOAAccessType on l.LOAAccessTypeId equals lat.LOAAccessTypeId
join ar in dbRRSP.AgentRepresentative on l.EMDRepresentativeId equals ar.AgentRepresentativeId
join arp in dbRRSP.Person on ar.PersonId equals arp.PersonId
where
l.PersonId == personId
select new
{
LOAOrReferredByDescription = lrb.LoaOrReferredByDescription,
lat.LOAAccessTypeDescription,
PersonType = "EMD Rep",
LOAName = arp.FirstName + ' ' + arp.LastName, l.DateAdded
};
var qryLOAPerson = from l in dbRRSP.LOA
join lrb in dbRRSP.LOAOrReferredBy on l.LOAOrReferredById equals lrb.LoaOrReferredById
join lat in dbRRSP.LOAAccessType on l.LOAAccessTypeId equals lat.LOAAccessTypeId
join lp in dbRRSP.LOAPerson on l.LOAPersonId equals lp.LOAPersonId
where
l.PersonId == personId
select new
{
LOAOrReferredByDescription = lrb.LoaOrReferredByDescription, lat.LOAAccessTypeDescription,
PersonType = "Person",
LOAName = lp.LOAPersonName,
l.DateAdded
};
This is the four queries. And the trickiest part is that the last field is a datetime, which is causing me some issues. I know how to union two of them together like this:
var qryMultipleLOA = qryIssuer.Union(qryEMD).ToList().Select(loa => new ExtendedLOA
{
LOAOrReferredByDescription = loa.LOAOrReferredByDescription,
LOAAccessTypeDescription = loa.LOAAccessTypeDescription,
PersonType = loa.PersonType,
LOAName = loa.LOAName,
DateAdded = DateTime.Parse(loa.DateAdded.ToString()).ToString("MM/dd/yyyy")
});
But I'm at a loss on how to add the last two queries - first I tried wrapping it in brackets and adding a .Union which didn't work, and then when I tried to nest them with appropriate .ToLists, that didn't work either.
Below is the code to bind it to the repeater.
rptLOA.DataSource = qryMultipleLOA;
rptLOA.DataBind();
Suggestions would be greatly appreciated.
Did you try something like?
var qryMultipleLOA = qryIssuer.Union(qryEMD).Union(qryEmdRep).Union(qryLOAPerson).ToList();
Provided your queries' footprints are the same, this shouldn't be an issue to chain them upon each other.
Edit:
I would also recommend the following:
Create a class to hold an instance of the resultant data.
Instead of creating lists of dynamic variables generated from Linq and hoping they all match, funnel the linq results into a List. That way you can tell immediately if you have a type mismatch.
Once you have four lists of the same List, Unions as per my syntax above will be a snap.
Dynamic Linq lists can be a pain, unwieldy and a single property type change can throw of your code at runtime rather than design time. If you follow the steps above, your code will be much more maintainable and clear to you and others.
I hope this helps in some way.

get count from Iqueryable<T> in linq-to-sql?

The following code doesn't seem to get the correct count.....
var materials = consRepository.FindAllMaterials().AsQueryable();
int count = materials.Count();
Is it the way to do it.... Here is my repository which fetches records...
public IQueryable<MaterialsObj> FindAllMaterials()
{
var materials = from m in db.Materials
join Mt in db.MeasurementTypes on m.MeasurementTypeId equals Mt.Id
where m.Is_Deleted == 0
select new MaterialsObj()
{
Id = Convert.ToInt64(m.Mat_id),
Mat_Name = m.Mat_Name,
Mes_Name = Mt.Name,
};
return materials;
}
Edit:
when i use this,
var materials = consRepository.FindAllMaterials().AsQueryable();
return View("Materials", materials);
I get 18 rows in my table... So y cant i get the count as 18 instead it gives 12
Ans:
Breakpoint doesn't seem produce me the result but response.Write(count) did...
This should get the correct count:
int count = consRepository.FindAllMaterials().Count();
How are you iterating through the model in your view?
Is it possible that you are displaying duplicate entries?
Is it possible that you're not joining on the correct columns? The only reason I ask is that your id columns aren't consistently named in each class. For Materials you are using Mat_id, but in MeasurementTypes you are using simply, Id. It makes me wonder if you're trying to join a natural key value against an artificial primary key instead of the corresponding natural foreign key.

Resources