Extracting Items over an List<T> of List<T> - c#

I am trying to retrieve records from a List<T> of List<T> and seek your help in getting it.
I am trying to fetch items where overdues.Accounts.AccountId = 'JKB1' and how can i do it over the below List Items.
public class OverdueModel
{
public string Slab { get; set; }
public double Value { get; set; }
public double Percentage { get; set; }
public List<OverdueSlabAccounts> Accounts { get; set; }
}
public class OverdueSlabAccounts
{
public string AccountId { get; set; }
public string AccountName { get; set; }
public string SalesCode { get; set; }
public string Value { get; set; }
}
void Main(){
List<OverdueModel> overdues = new List<OverdueModel>();
List<OverdueSlabAccounts> accounts = new List<OverdueSlabAccounts>();
//For T3
accounts.Clear();
accounts.Add(new OverdueSlabAccounts()
{
AccountId = "JKB1",
AccountName = "JKB1",
SalesCode = "JKB",
Value = "500"
});
accounts.Add(new OverdueSlabAccounts()
{
AccountId = "JKB2",
AccountName = "JKB2",
SalesCode = "JKB",
Value = "500"
});
overdues.Add(new OverdueModel()
{
Slab = "T3",
Value = 1000,
Percentage = 0,
Accounts = accounts
});
//For T4
accounts.Clear();
accounts.Add(new OverdueSlabAccounts()
{
AccountId = "JKB1",
AccountName = "JKB1",
SalesCode = "JKB",
Value = "1000"
});
overdues.Add(new OverdueModel()
{
Slab = "T4",
Value = 1000,
Percentage = 0,
Accounts = accounts
});
}

You can use Where and Any in combination for this :
var result = overdues
.Where(overdue => overdue.Accounts
.Any(account => account.AccountId == "JKB1"));
This will filter those overdues for which associated any Account has AccountId JKB1

You could use Linq for the purpose
var filteredList = overdues.Where(x=>x.Accounts.Any(c=>c.AccountId=="JKB1"));
For more information on Where and Any
Enumerable.Where : Refer
Enumerable.Any : Refer
Output

You can try this:
var account = accounts.Find(x => x.AccountId.Contains("JKB1")));
or
var account = accounts.Find(x => x.AccountId.Equals("JKB1")));
this will get you the specific account Id you are looking for.

Related

Creating dynamic range aggregations in Nest

I have a set of POCO facets with ranges, that I have received from a client. I need to convert these ultimately into an AggregationDictionary. I cannot figure out the syntax for creating a dynamic set of aggregations (possilbly of type RangeAggregationDescriptor) and need help with this.
My POCO objects are below:
public class TypedFacets
{
public string Name { get; set; }
public string Field { get; set; }
public IReadOnlyCollection<Range> RangeValues { get; set; } = new List<Range>();
public int Size { get; set; }
}
public class Range
{
public string Name { get; set; }
public double? From { get; set; }
public double? To { get; set; }
}
The Nest generation looks like below:
var facets = new List<TypedFacets>()
{
new TypedFacets()
{
Name = "potatoRange",
Field = "potatoRange",
RangeValues = new List<Range>()
{
new Range()
{
From = 0,
To = null,
Name = "chips"
},
new Range()
{
From = 1,
To = null,
Name = "crisps"
}
}
}
};
var aggregations = new AggregationContainerDescriptor<Template>();
facets.Where(f => f.RangeValues.Any()).ToList().ForEach(f =>
{
var rad = new RangeAggregationDescriptor<Template>();
f.RangeValues.ToList().ForEach(rangeValue =>
{
rad = rad.Ranges(rs => rs.From(rangeValue.From).To(rangeValue.To).Key(rangeValue.Name));
});
// this line doesn't work and needs to change
aggregations.Range(f.Name, r => r
.Field(f.Field).Ranges(rs => rad.Ranges));
});
return ((IAggregationContainer)aggregations).Aggregations;
I'm not sure how to fix the above. Any help would be appreciated.
I eventually found the solution for this. You can create the dynamic ranges as per below
private Func<AggregationRangeDescriptor, IAggregationRange>[] CreateRangeRanges(TypedFacets rangedAgg)
{
var rangeRanges = new List<Func<AggregationRangeDescriptor, IAggregationRange>>();
rangedAgg.RangeValues.ToList().ForEach(rangeValue =>
{
rangeRanges.Add(rs => rs.From(rangeValue.From).To(rangeValue.To).Key(rangeValue.Name));
});
return rangeRanges.ToArray();
}
And then assing them like below
facets.Where(f => f.RangeValues.Any()).ToList().ForEach(f =>
{
aggregations.Range(f.Name, r => r
.Field(f.Field).Ranges(CreateRangeRanges(f)));
});

Filter data from 2 lists with diferent models C#

I have this models
public class RoutingAttributeModel
{
public int Bus_No { get; set; }
public int Attribute_No { get; set; }
public string Attribute_Name { get; set; }
public string Status { get; set; }
public string Notes { get; set; }
}
public class AgentRoutingAttributeModel
{
public int Agent_No { get; set; }
public int Bus_No { get; set; }
public int Attribute_No { get; set; }
public string Attribute_Name { get; set; }
public string Status { get; set; }
}
List<RoutingAttributeModel> lstComplete = new List<RoutingAttributeModel>();
List<AgentRoutingAttributeModel> lstAssigned = new List<AgentRoutingAttributeModel>();
Filled this with some data
Is it possible to filter with Linq? I want to save in a new list the diferent content between lstComplete and lstAssigned
I was trying to join both lists but got stuck there
var results1 = from cl in lstComplete
join al in lstAssigned
on cl.Attribute_No equals al.Attribute_No
select cl;
you can use linq
as my understanding, you try to find linked by attribute_No records and have a list of not matching properties?
lstComplete.Add(new RoutingAttributeModel(){
Attribute_Name = "aaa",
Attribute_No = 1,
Bus_No = 1,
Notes = "",
Status = "status"
});
lstAssigned.Add(new AgentRoutingAttributeModel()
{
Attribute_No = 1,
Agent_No = 10,
Bus_No = 1,
Attribute_Name = "bbb",
Status = "status2"
});
var lst = lstComplete
.Join(lstAssigned,
complete => complete.Attribute_No,
assigned => assigned.Attribute_No,
(complete, assigned) => new { lstComplete = complete, lstAssigned = assigned })
.Select(s => new { s.lstComplete, s.lstAssigned})
.Where(w=>
w.lstAssigned.Attribute_Name != w.lstComplete.Attribute_Name
|| w.lstAssigned.Bus_No != w.lstComplete.Bus_No
)
.ToList()
.Dump();
so result would be
You could try the following query
var filteredList = lstComplete
.Where(x => !lstAssigned.Any(y => y.Attribute_No == x.Attribute_No));

Multiple Aggregation Levels in Linq

I am not sure what my issue to be called, although I mentioned in the subject as "Multiple Aggregation Levels".
I would like to Aggregate different dimensions of the data presented. In this Example, I am trying to get Aggregation data by SalesCode and in Detail Aggregation by AccountId. So basically, I could get the Accounts that were associated to the Sales Aggregation Level.
Hence the output I am ought to get should be like this:
My Requirement is to Map the data to the following Class:
public class Earning
{
public string EntityId
{
get;
set;
}
public string EntityName
{
get;
set;
}
public string EntityType
{
get;
set;
}
public int TradeCount
{
get;
set;
}
public int OrderCount
{
get;
set;
}
public decimal PrincipalAmount
{
get;
set;
}
public decimal GrossBrokerage
{
get;
set;
}
public decimal NetBrokerage
{
get;
set;
}
public List<Earning> Detail
{
get;
set;
}
}
From the following data:
List<Trade> Trades = new List<Trade>(){
new Trade{
AccountId = "ACT01",
SalesCode = "STEVES",
PrincipalAmount = 100,
GrossBrokerage = 0.64M,
NetBrokerage = 0.64M
},
new Trade{
AccountId = "ACT02",
SalesCode = "STEVES",
PrincipalAmount = 100,
GrossBrokerage = 0.64M,
NetBrokerage = 0.64M
},
new Trade{
AccountId = "ACT01",
SalesCode = "STEVES",
PrincipalAmount = 50,
GrossBrokerage = 0.32M,
NetBrokerage = 0.32M
},
new Trade{
AccountId = "ACT03",
SalesCode = "GRAHAMS",
PrincipalAmount = 100,
GrossBrokerage = 0.64M,
NetBrokerage = 0.64M
},
};
Until now I have tried the following ways in the working I am mentioning below, but I am clueless to get the 2nd Level aggregation, which is by AccountId.
DotNetFiddle: https://dotnetfiddle.net/SxGdDD
The Trade Class look like this:
public class Trade
{
public string AccountId
{
get;
set;
}
public string SalesCode
{
get;
set;
}
public decimal PrincipalAmount
{
get;
set;
}
public decimal GrossBrokerage
{
get;
set;
}
public decimal NetBrokerage
{
get;
set;
}
}
You need another GroupBy.
var results = (
from r in Trades
group r by r.SalesCode
into g
select new Earning()
{
EntityId = g.Key.ToString(),
EntityName = g.Key.ToString(),
TradeCount = g.Count(),
OrderCount = g.Count(),
PrincipalAmount = g.Sum(c => c.PrincipalAmount),
GrossBrokerage = g.Sum(c => c.GrossBrokerage),
NetBrokerage = g.Sum(c => c.NetBrokerage),
Detail = g.GroupBy(c=>c.AccountId).Select(c => new Earning()
// Added GroupBy ---^^
{
EntityId = c.Key,
EntityName = c.Key,
TradeCount = c.Count(),
OrderCount = c.Count(),
PrincipalAmount = c.Sum(p=>p.PrincipalAmount),
GrossBrokerage = c.Sum(p=>p.GrossBrokerage),
NetBrokerage = c.Sum(p=>p.NetBrokerage),
}).ToList(),
}).ToList();
foreach (var item in results)
{
Console.WriteLine(item.EntityId);
Console.WriteLine(string.Format("Total Principal Amount: {0}", item.PrincipalAmount.ToString()));
Console.WriteLine(string.Format("Total Gross Brokerage Amount: {0}", item.GrossBrokerage.ToString()));
Console.WriteLine(string.Format("Total Net Brokerage Amount: {0}", item.NetBrokerage.ToString()));
foreach (Earning detail in item.Detail)
{
Console.WriteLine(string.Format("-- Detail {0}/{1}", detail.EntityId, detail.EntityName));
}
}

Find Unique count on field using LINQ

I am trying to determine the Distinct count for a particular field in a collection of objects.
private static RemittanceCenterBatchSummaryListModel SummarizeFields(RemittanceCenterSummaryListModel remittanceCenterSummaryListModel)
{
var result = remittanceCenterSummaryListModel.RemittanceBatchSummaryRecord.GroupBy(x => new{x.FileId, x.SourceFileName, x.BatchCode, x.BatchType})
.Select(x => new RemittanceCenterBatchSummarizedModel()
{
FileId = x.Key.FileId,
SourceFileName = x.Key.SourceFileName,
BatchCode = x.Key.BatchCode,
BatchType = x.Key.BatchType,
DetailRecordCountAdc = x.Count(y => y.BillingSystemCode == BillingSystemCode.Adc),
DetailRecordCountNotAdc = x.Count(y => y.BillingSystemCode == BillingSystemCode.Exd),
AmountAdc = x.Where(y => y.BillingSystemCode == BillingSystemCode.Adc).Sum(y => y.PaymentAmount),
AmountNotAdc = x.Where(y => y.BillingSystemCode == BillingSystemCode.Exd).Sum(y => y.PaymentAmount),
UniqueFileCount = x.Select(y => x.Key.FileId).Distinct().Count()
});
return CreateSummaryListModel(result);
}
Input entities:
public class RemittanceCenterSummaryListModel
{
public RemittanceCenterSummaryListModel()
{
this.RemittanceBatchSummaryRecord = new List<RemittanceBatchProcessingModel>();
}
public List<RemittanceBatchProcessingModel> RemittanceBatchSummaryRecord { get; private set; }
}
public class RemittanceCenterBatchSummarizedModel
{
public string FileId { get; set; }
public string SourceFileName { get; set; }
public string BatchCode { get; set; }
public string BatchType { get; set; }
public int DetailRecordCountAdc { get; set; }
public int DetailRecordCountNotAdc { get; set; }
public int DetailRecordCountTotal { get; set; }
public decimal AmountAdc { get; set; }
public decimal AmountNotAdc { get; set; }
public decimal AmountTotal { get; set; }
public BillingSystemCode BillingSystemCode { get; set; }
public int UniqueFileCount { get; set; }
}
private static RemittanceCenterBatchSummaryListModel CreateSummaryListModel(IEnumerable<RemittanceCenterBatchSummarizedModel> summaryModels)
{
var summaryModelList = new RemittanceCenterBatchSummaryListModel();
foreach (var summaryRec in summaryModels)
{
var summaryModel = new RemittanceCenterBatchSummarizedModel
{
FileId = summaryRec.FileId,
SourceFileName = summaryRec.SourceFileName,
BatchCode = summaryRec.BatchCode,
BatchType = summaryRec.BatchType,
DetailRecordCountAdc = summaryRec.DetailRecordCountAdc,
DetailRecordCountNotAdc = summaryRec.DetailRecordCountNotAdc,
AmountAdc = summaryRec.AmountAdc,
AmountNotAdc = summaryRec.AmountNotAdc,
UniqueFileCount = summaryRec.UniqueFileCount
};
summaryModelList.RemittanceBatchSummary.Add(summaryModel);
}
return summaryModelList;
}
Example input records:
Record1:
FileId: '123'
SourceFileName: 'test.file.txt'
BatchCode: 'aaa'
BatchType: 'scanned'
PaymentAmount: '50.00'
BillingSystemCode: 'Adc'
Record1:
FileId: '1234'
SourceFileName: 'test.file2.txt'
BatchCode: 'aab'
BatchType: 'scanned'
PaymentAmount: '52.00'
BillingSystemCode: 'Adc'
ActualOuput for UniqueFileCount Field:
UniqueFileCount = 1
ExpectedOutput results for UniqueFileCount Field:
UniqueFileCount = 2
What am I doing wrong?
It sounds like you want the distinct count of FileId for the entire collection and not just for each group, which will always be 1 since FileId is one of the fields you group on. If that is the case then you can just calculate that count first
int distinctFileIds = remittanceCenterSummaryListModel.RemittanceBatchSummaryRecor‌​d
.Select(x => x.FileId)
.Distinct()
.Count();
Then use that in your Linq query
UniqueFileCount = distinctFileIds

max and group by question with LINQ

I want to group the below query by GetSetDomainName and select the row which has the maximum GetSetKalanGun.In other words, I am trying to get the row with the maximum KALANGUN among those which have the same DOMAINNAME.
var kayitlar3 = (
from rows in islemDetayKayitListesi
select new
{
KAYITNO = rows.GetSetKayitNo,
HESAPADI = rows.GetSetHesapAdi,
URUNNO = rows.GetSetUrunNo,
URUNADI = rows.GetSetUrunAdi,
URUNMIKTAR = rows.GetSetUrunMiktar,
ISLEMTARIHI = rows.GetSetIslemTarihi,
HIZMETDURUMU = rows.GetSetHizmetDurumu,
TOPLAMTUTAR = rows.GetSetToplamTutar,
HIZMETBASLANGICTARIHI = rows.GetSetHizmetBaslangicTarihi,
HIZMETBITISTARIHI = rows.GetSetHizmetBitisTarihi,
KALANGUN = rows.GetSetKalanGun
DOMAINNAME = rows.GetSetDomainName,
SIPARISDURUMU = rows.GetSetSiparisDurumu
}).AsQueryable();
This is what I get
KAYITNO DOMAINNAME KALANGUN
1 asdf.com 30
2 domnam.com 172
3 asdf.com 40
4 xyz.com 350
This is what I want
KAYITNO DOMAINNAME KALANGUN
2 domnam.com 172
3 asdf.com 40
4 xyz.com 350
var islemDetayKayitListesi = new List<IslemDetayKayit>();
islemDetayKayitListesi get filled with a foreach loop, with no problem
And that is what IslemDetayKayit looks like
public class IslemDetayKayit
{
public int GetSetKayitNo { get; set; }
public string GetSetHesapAdi { get; set; }
public string GetSetUrunNo { get; set; }
public string GetSetUrunAdi { get; set; }
public double GetSetUrunMiktar { get; set; }
public string GetSetIslemTarihi { get; set; }
public string GetSetHizmetDurumu { get; set; }
public string GetSetToplamTutar { get; set; }
public string GetSetHizmetBaslangicTarihi { get; set; }
public string GetSetHizmetBitisTarihi { get; set; }
public int GetSetKalanGun { get; set; }
public string GetSetSiparisDurumu { get; set; }
public string GetSetDomainName { get; set; }
}
EDIT : I figured out that there was some other problem in my code, and corrected it.After that all the answer I had to this question works.Thank you for helping and teaching me new things.
This will do the trick:
var q =
from item in kayitlar3
group item by item.DOMAINNAME into g
select g.OrderByDescending(i => i.KALANGUN).First();
You can also try this:
var q =
from row in islemDetayKayitListesi
group row by row.GetSetDomainName into g
let highest = g.OrderByDescending(r => r.GetSetKalanGun).First()
select new
{
KAYITNO = highest.GetSetKayitNo,
DOMAINNAME = g.Key,
KALANGUN = highest.GetSetKalanGun
};
Note that this would yield the same results. If it doesn't, there is a problem with your code that we can't see by looking at the information that you posted.
You could use:
var kayitlar3 =
islemDetayKayitListesi.
Select(rows =>
new
{
KAYITNO = rows.GetSetKayitNo,
HESAPADI = rows.GetSetHesapAdi,
URUNNO = rows.GetSetUrunNo,
URUNADI = rows.GetSetUrunAdi,
URUNMIKTAR = rows.GetSetUrunMiktar,
ISLEMTARIHI = rows.GetSetIslemTarihi,
HIZMETDURUMU = rows.GetSetHizmetDurumu,
TOPLAMTUTAR = rows.GetSetToplamTutar,
HIZMETBASLANGICTARIHI = rows.GetSetHizmetBaslangicTarihi,
HIZMETBITISTARIHI = rows.GetSetHizmetBitisTarihi,
KALANGUN = rows.GetSetKalanGun,
DOMAINNAME = rows.GetSetDomainName,
SIPARISDURUMU = rows.GetSetSiparisDurumu
}).
GroupBy(a =>
//To ignore case and trailing/leading whitespace
a.DOMAINNAME.ToUpper().Trim()).
Select(g =>
g.OrderByDescending(a => a.KALANGUN).FirstOrDefault()).
AsQueryable();
EDIT:
So using this code:
List<Thing> islemDetayKayitListesi = new List<Thing>();
Thing a = new Thing() { GetSetDomainName = "abc.com", GetSetKayitNo = 1,
GetSetKalanGun = 40 };
Thing b = new Thing() { GetSetDomainName = "abc.com", GetSetKayitNo = 2,
GetSetKalanGun = 300 };
Thing c = new Thing() { GetSetDomainName = "xyz.com", GetSetKayitNo = 3,
GetSetKalanGun = 400 };
Thing d = new Thing() { GetSetDomainName = "123.com", GetSetKayitNo = 4,
GetSetKalanGun = 124 };
islemDetayKayitListesi.Add(a);
islemDetayKayitListesi.Add(b);
islemDetayKayitListesi.Add(c);
islemDetayKayitListesi.Add(d);
var kayitlar3 =
islemDetayKayitListesi.
Select(rows =>
new
{
KAYITNO = rows.GetSetKayitNo,
HESAPADI = rows.GetSetHesapAdi,
URUNNO = rows.GetSetUrunNo,
URUNADI = rows.GetSetUrunAdi,
URUNMIKTAR = rows.GetSetUrunMiktar,
ISLEMTARIHI = rows.GetSetIslemTarihi,
HIZMETDURUMU = rows.GetSetHizmetDurumu,
TOPLAMTUTAR = rows.GetSetToplamTutar,
HIZMETBASLANGICTARIHI = rows.GetSetHizmetBaslangicTarihi,
HIZMETBITISTARIHI = rows.GetSetHizmetBitisTarihi,
KALANGUN = rows.GetSetKalanGun,
DOMAINNAME = rows.GetSetDomainName,
SIPARISDURUMU = rows.GetSetSiparisDurumu
}).
GroupBy(anon =>
anon.DOMAINNAME).
Select(g =>
g.OrderByDescending(anon => anon.KALANGUN).First()).
AsQueryable();
kayitlar3.ToList().
ForEach(anon => Console.WriteLine("{0}, {1}, {2}",
anon.KAYITNO, anon.DOMAINNAME, anon.KALANGUN));
struct Thing
{
public int GetSetKayitNo { get; set; }
public int GetSetHesapAdi { get; set; }
public int GetSetUrunNo { get; set; }
public int GetSetUrunAdi { get; set; }
public int GetSetUrunMiktar { get; set; }
public int GetSetIslemTarihi { get; set; }
public int GetSetHizmetDurumu { get; set; }
public int GetSetToplamTutar { get; set; }
public int GetSetHizmetBaslangicTarihi { get; set; }
public int GetSetHizmetBitisTarihi { get; set; }
public int GetSetKalanGun { get; set; }
public string GetSetDomainName { get; set; }
public int GetSetSiparisDurumu { get; set; }
}
I get the expected output:
2, abc.com, 300
3, xyz.com, 400
4, 123.com, 124
After clarification about your desired output, this will return the row with the top KALANGUN per DOMAINNAME:
var kayitlar3 = (
from rows in islemDetayKayitListesi
select new
{
KAYITNO = rows.GetSetKayitNo,
HESAPADI = rows.GetSetHesapAdi,
URUNNO = rows.GetSetUrunNo,
URUNADI = rows.GetSetUrunAdi,
URUNMIKTAR = rows.GetSetUrunMiktar,
ISLEMTARIHI = rows.GetSetIslemTarihi,
HIZMETDURUMU = rows.GetSetHizmetDurumu,
TOPLAMTUTAR = rows.GetSetToplamTutar,
HIZMETBASLANGICTARIHI = rows.GetSetHizmetBaslangicTarihi,
HIZMETBITISTARIHI = rows.GetSetHizmetBitisTarihi,
KALANGUN = rows.GetSetKalanGun
DOMAINNAME = rows.GetSetDomainName,
SIPARISDURUMU = rows.GetSetSiparisDurumu
})
.GroupBy(rr => rr.DOMAINNAME)
.SelectMany(gg => gg.OrderByDescending(rr => rr.KALANGUN).First());
Try
from rows in islemDetayKayitListesi
group rows by new { rows.GetSetDomainName} into results
let MaxKALANGUN = results.Max(i=>i.KALANGUN)
select new
{
KAYITNO = results.First(i=>i.KALANGUN== MaxKALANGUN).GetSetKayitNo
DOMAINNAME = results.Key.GetSetDomainName ,
KALANGUN = MaxKALANGUN
}
If you want the complete class, try
from rows in islemDetayKayitListesi
group rows by new { rows.GetSetDomainName} into results
let MaxKALANGUN = results.Max(i=>i.KALANGUN)
select results.First(i=>i.KALANGUN== MaxKALANGUN)

Categories