I am using the below logic to merge List rows in a list together if they have all have identical columns apart from one (OtherAuditeesUserName). In which case i join the different values of OtherAuditeesUserName with a comma seperater
The original list looks like this:
TrailRemarkId,PreviousAudit,OtherAuditees,StrategicPriority,Observations,DocumentsReviewed
1,"old audit","jane smith", 1,none, doc.docx
1,"old audit","john collins", 1,none, doc.docx
The end result I am looking for is :
TrailRemarkId,PreviousAudit,OtherAuditees,StrategicPriority,Observations,DocumentsReviewed
1,"old audit","jane smaith, john collins", 1,none, doc.docx
see how OtherAuditees is joined using a comma.
Can someone point out a more efficient way to merge List rows ?
var trailRemarks = (from a in auditData
select new
{
a.TrailRemarkId,
a.PreviousAudit,
a.OtherAuditees,
a.StrategicPriority,
a.Observations,
a.DocumentsReviewed,
}).Distinct();
List<TrailRemarkEntity> trlist = new List<TrailRemarkEntity>() ;
int? trId = 0;
foreach (var tr in trailRemarks)
{
if (trId == 0 || (trId != tr.TrailRemarkId))
{
trlist.Add(
new TrailRemarkEntity()
{
TrailRemarkId = tr.TrailRemarkId ?? 0,
PreviousAuditName = tr.PreviousAudit,
DocumentsReviewed = tr.DocumentsReviewed,
StrategicPriorityName = tr.StrategicPriority,
OtherAuditeesUserName = tr.OtherAuditees,
Observations = tr.Observations
}
);
}
else
{
var existingTR = trlist.Last();
existingTR.OtherAuditeesUserName += ", " + tr.OtherAuditees;
}
trId = tr.TrailRemarkId;
}
You can use group by and string.join for doing it like below,
List<TrailRemarkEntity> trailRemarks = (from a in auditData
group a by new {
a.TrailRemarkId,
a.TrailRemarkId,
a.PreviousAudit,
a.StrategicPriority,
a.Observations,
a.DocumentsReviewed
} into groupedData
select new TrailRemarkEntity()
{
TrailRemarkId = groupedData.Key.TrailRemarkId ?? 0,
PreviousAuditName = groupedData.Key.PreviousAudit,
DocumentsReviewed = groupedData.Key.DocumentsReviewed,
StrategicPriorityName = groupedData.Key.StrategicPriority,
OtherAuditeesUserName = string.join("," , groupedData.Select(exp=>exp.OtherAuditees)),
Observations = groupedData.Key.Observations
}).ToList();
Hope it helps.
Thanks thisiva, your solution worked but I modified it slightly to remove duplicates as follows:
string.Join(",", groupedData.Select(exp => exp.OtherAuditees).Distinct())
Related
I want to retrieve data from Project.Models.transaction_details by using linq, comparing value from list of string (List).
here is my code
List<transaction_details> transactions = new List<transaction_details>();
List<string> date_list = new List<string>();
// date_list output is ["2020-01-01","2020-01-02",2020-01-03",...,"2020-01-31"]
while (sdr.Read())
{
transactions.Add(new transaction_details
{
ID = sdr.GetInt32("ID"),
Transdate = sdr.GetDateTime("Transdate"),
Debit = sdr.GetDecimal("Debit"),
TransactionName =sdr.GetString("TransactionName"),
BranchID = sdr.GetString("BranchID")
});
}
var array1Index = date_list.Select((i, index) => new { Index = index, i = i }).ToList();
List<transaction_details> arrayresult = new List<transaction_details>();
var query1 = from a in array1Index
select transactions.Contains(a.i) == true ? a.i : "";
arrayresult = query1.ToList();
arrayresult.ForEach(x => {
Console.Write(x + " ");
});
My problem is (a.i) is an error.
Cannot convert 'string' to 'Project.Models.transaction_details'.
you probably mean to check the transaction date. try this:
var query1 = from a in array1Index
select transactions.Any(t => t.Transdate == a.i) == true ? a.i : "";
EDIT:
if you want a list of transactions try this:
var query1 = from t in transactions
where array1Index.Any(a => a.i == t.Transdate)
select t;
var query1 = from t in transactions
where array1Index.Any(a => a.i == t.Transdate);
try this
I want to create a dynamic query with LINQ-to-SQL and everything works except for one thing: group by. I looked at the other questions but haven't found a reason so far why it does not work.
I use using System.Linq.Dynamic; with the following query (that works):
int numberOfRankedItems = 3;
string minMaxChoice = "max";
string orderBy = "";
if (minMaxChoice == "max")
{
orderBy = "queryGroup.Sum(row => row.POSITIONVALUE) descending";
} else if (minMaxChoice == "min")
{
orderBy = "queryGroup.Sum(row => row.POSITIONVALUE) ascending";
}
string minMaxFeatureColumnName = "BRANDNAME";
string selectMinMaxFeature = "new { minMaxFeature = queryGroup.Key." + minMaxFeatureColumnName + ", sumPosition = queryGroup.Sum(row => row.POSITIONVALUE)}";
var query = (from tableRow in Context.xxx
where /* some filters */
group tableRow by tableRow.BRANDNAME into queryGroup
orderby orderBy
select selectMinMaxFeature).Take(numberOfRankedItems).ToList();
The use of variables for orderby and select works fine, but for group by not no matter what I try to replace with a variable. The query actually works if I e.g. use a variable instead of tableRow.BRANDNAME but the query returns the wrong result. The goal is to be able to set the column for the grouping dynamically.
Ideas?
Thanks
Edit: there seem to be multiple issues also with the other variables. So I generalize the question a bit: how can I generalize the following query in terms of
The column to group by
The column to order by + ASC or DESC
In the select statement the columnname of the first statement (BRANDNAME)
Here is the query:
var query = (from tableRow in ctx.xxx
where /* filter */
group tableRow by new { tableRow.BRANDNAME } into queryGroup
orderby queryGroup.Sum(row => row.POSITIONVALUE) descending
select new { minMaxFeature = queryGroup.Key.BRANDNAME, sumPosition = queryGroup.Sum(row => row.POSITIONVALUE) }).Take(numberOfRankedItems).ToList();
Would be great without expression trees ;)
I have now elaborated a solution to the question:
The solution uses as before using System.Linq.Dynamic; allows now to set certain variables. In the end it returns a dictionary.
// set variables
int numberOfRankedItems;
if (queryData.NumberOfRankedItems != null)
{
numberOfRankedItems = (int) queryData.NumberOfRankedItems;
} else
{
numberOfRankedItems = 0;
}
string minMaxChoice = queryData.MinMaxChoice;
string minMaxFeatureColumnName = queryData.MinMaxFeatureColumnName;
string orderByPrompt = "";
if (minMaxChoice == "max")
{
orderByPrompt = "it.Sum(POSITIONVALUE) descending";
} else if (minMaxChoice == "min")
{
orderByPrompt = "it.Sum(POSITIONVALUE) ascending";
}
string groupByPrompt = queryData.MinMaxFeatureColumnName;
// execute query
IQueryable query = (from tableRow in Context.xxx
where /* some filters */
select tableRow).
GroupBy(groupByPrompt, "it").
OrderBy(orderByPrompt).
Select("new (it.Key as minMaxFeature, it.Sum(POSITIONVALUE) as sumPosition)").
Take(numberOfRankedItems);
// create response dictionary
Dictionary<int?, Dictionary<string, int?>> response = new Dictionary<int?, Dictionary<string, int?>>();
int count = 1;
foreach (dynamic item in query)
{
string minMaxFeatureReturn = item.GetType().GetProperty("minMaxFeature").GetValue(item);
int? sumPositionReturn = item.GetType().GetProperty("sumPosition").GetValue(item);
response[count] = new Dictionary<string, int?>() { { minMaxFeatureReturn, sumPositionReturn } };
count++;
}
return response;
I have been searching for the solution to this problem and this is what I have so far:
var ProductInfo = (from p in twd.Products
orderby p.PC
where p.DELMARK == active
select p).AsEnumerable();
var BuyersData =
(from x in db.MinimumProductInfo
where x != null
orderby x.ItemCode, x.Region
let pnote =
(from pn in db.ProductNotes
where pn != null
where x.MinimumProductInfoID == pn.MinimumProductInfoID
&& pn.NoteTypeFlag == "p"
orderby pn.NoteDate descending
select pn).FirstOrDefault()
let cnote =
(from c in db.ProductNotes
where c != null
where x.MinimumProductInfoID == c.MinimumProductInfoID
&& c.NoteTypeFlag == "c"
orderby c.NoteDate descending
select c).FirstOrDefault()
let product =
(from p in ProductInfo
where x.ItemCode == p.PC
select p).FirstOrDefault()
select new ProductInfoWithNoteList
{
MinimumProductInfoID = x.MinimumProductInfoID,
ItemCode = x.ItemCode,
EquivCode = x.EquivCode,
Description = product.PDESC,
MinimumOnHandQuantity = x.MinimumOnHandQuantity,
MaximumOHandQuantity = x.MaximumOHandQuantity,
MinimumOrderQuantity = x.MinimumOrderQuantity,
LeadTimeInWeeks = x.LeadTimeInWeeks,
Region = x.Region,
Comment = cnote.ItemNote,
PermanentNote = pnote.ItemNote
}).ToArray();
It looks correct but I am getting an error,
'The specified LINQ expression contains references to queries that are
associated with different contexts.'
What this code is supposed to do is pull out all the active product codes from the first table using the twd datacontext then use data from that database in the db.MinimumProductInfo table. The reason they have 2 separate data contexts are they are completely different databases, the first is our ERP and the second is one that we are building in house.
What am I missing? I know it is possible to do this by separating the two datacontexts then adding them together because I have seen it done with single instances but I cannot find how to do it with list data.
Instead of this:
let product =
(from p in ProductInfo
where x.ItemCode == p.PC
select p).FirstOrDefault()
select new ProductInfoWithNoteList
{
MinimumProductInfoID = x.MinimumProductInfoID,
ItemCode = x.ItemCode,
EquivCode = x.EquivCode,
Description = product.PDESC,
MinimumOnHandQuantity = x.MinimumOnHandQuantity,
MaximumOHandQuantity = x.MaximumOHandQuantity,
MinimumOrderQuantity = x.MinimumOrderQuantity,
LeadTimeInWeeks = x.LeadTimeInWeeks,
Region = x.Region,
Comment = cnote.ItemNote,
PermanentNote = pnote.ItemNote
}).ToArray();
Try this by removing the let product clause and not filling the properties associated with ProductInfo because we will do that afterwards (See I have commented out the Description property):
select new ProductInfoWithNoteList
{
MinimumProductInfoID = x.MinimumProductInfoID,
ItemCode = x.ItemCode,
EquivCode = x.EquivCode,
//Description = product.PDESC,
MinimumOnHandQuantity = x.MinimumOnHandQuantity,
MaximumOHandQuantity = x.MaximumOHandQuantity,
MinimumOrderQuantity = x.MinimumOrderQuantity,
LeadTimeInWeeks = x.LeadTimeInWeeks,
Region = x.Region,
Comment = cnote.ItemNote,
PermanentNote = pnote.ItemNote
}).ToArray();
Now that you have your BuyersData and ProductInfo in memory, set the Description property or all the items in BuyersData:
foreach(var thisBuyerData in BuyersData)
{
var thisPi = ProductInfo.SingleOrDefault(x => x.PC == thisBuyerData.ItemCode);
thisBuyerData.Description = thisPi?.PDESC;
}
I've table with following data.
I want to group the data by DocumentID and then want to marge the DocPropIdentifyName and meta value together using comma separator. The output will be like following:
I'm doing it by using a foreach like below:
var test = (from r in lstDocSearch
group r by r.DocumentID
into g
select new
{
DocumentID = g.Key,
MetaValues = g.ToList()
}).ToList();
List<DocSearch> list = new List<DocSearch>();
foreach (var item in test)
{
foreach (var item2 in item.MetaValues)
{
var check = list.Exists(x => x.DocumentID == item2.DocumentID);
if (check)
{
var find = list.FirstOrDefault(x => x.DocumentID == item2.DocumentID);
find.MetaValue = find.MetaValue + ", " + item2.MetaValue;
find.DocPropIdentifyName = find.DocPropIdentifyName + ", " + item2.DocPropIdentifyName;
}
else
{
DocSearch objDocSearch = new DocSearch();
objDocSearch.DocumentID = item2.DocumentID;
objDocSearch.DocPropIdentifyID = item2.DocPropIdentifyID;
objDocSearch.DocPropIdentifyName = item2.DocPropIdentifyName;
objDocSearch.MetaValue = item2.MetaValue;
list.Add(objDocSearch);
}
}
}
But I would like to do this with linq rather than looping through the collection. Is it possible?
Do you mean something like this ? :
var test = (from r in lstDocSearch
group r by r.DocumentID
into g
select new
{
DocumentID = g.Key,
MetaValues = String.Join(",", g.Select(o => o.MetaValue)),
DocPropIdentifyNames = String.Join(",", g.Select(o => o.DocPropIdentifyName)),
}).ToList();
~ error says image seen below i don't know why is it? is there another way to pick up the data without the error? i'm using distinct or group by.
var query = (from i in SFC.TransacRRrecords where i.POPRCTNM == p
group i by new {
i.VendorID,
i.VENDNAME,
i.SUBTOTAL,
i.PymtrMID,
i.TRUCKNO,
i.REMARKS,
i.VPNum,
i.VPDate,
i.AmountInWords
} into grp
select new
{
Vcode = grp.Key.VendorID,
Vdesc = grp.Key.VENDNAME,
Vsubtotal = grp.Key.SUBTOTAL,
Vterms = grp.Key.PymtrMID,
Vtruckno = grp.Key.TRUCKNO,
Vremarks = grp.Key.REMARKS,
Vvpno = grp.Key.VPNum,
Vvpdate = grp.Key.VPDate,
Vamntword = grp.Key.AmountInWords
}).FirstOrDefault();
ListViewItem List = new ListViewItem(query.Vcode);
List.SubItems.Add(query.Vdesc);
List.SubItems.Add(string.Format("{0:n2}", query.Vsubtotal));
List.SubItems.Add(query.Vterms);
List.SubItems.Add(query.Vtruckno);
List.SubItems.Add(query.Vremarks);
List.SubItems.Add(query.Vvpno);
List.SubItems.Add(query.Vvpdate);
List.SubItems.Add(query.Vamntword);
deletedRRHeaderList.Items.AddRange(new ListViewItem[] { List });