in List<file> i have data :
id Initial B
1 G (2016-27-12)
2 H (2016-27-15)
3 G (2016-27-16)
//my code
List<file> i = new List<file>;
var r = i.Select(i=> i.Initial).GroupBy(x => new { r = x.to List() });
for( int i = 0; i < r.Count(); i++ )
{
comboBox1.Items.Add(r[i].ToString());
}
but my code still error.
how to GroupBy() with linq and each Initial result 2 count value G & H?
You can use
var r = i.Select(i=> i.Initial).GroupBy(x =>x).ToList();
Other way with Distinct()
var r = i.Select(i=> i.Initial).Distinct().ToList();
I dont know if thats what you are trying to do but to me it looks like you want to get every unique Initial from your list. To accomplish that, you can use "Distinct":
var r = i.Select(i=> i.Initial).Distinct();
If this is not what you are trying to do, please provide more info.
Related
I have problem with nested foreach loops because of following example:
var someList = new List<SimpleC>();
simpleA = database.SimpleA.ToList();
simpleB = database.SimpleB.ToList();
foreach (var a in simpleA)
{
foreach (var b in simpleB)
{
var c = new simpleC();
c.simpleAId = a.Id;
c.simpleAName = a.Name;
c.simpleBName = b.Name;
someList.Add(c);
}
}
return someList;
The problem: imagine first iteration it goes to first foreach loop then to second foreach loop it initiates new object, maps values and adds newly initiated object to new list, but when second iteration comes instead of going back to first foreach loop it continues with second foreach loop and it loops through second until it finishes, I understand that's how C# works, but I need side effect for it to continue to first foreach loop to get new values.
You would be much better served by not trying to iterate this manually, establishing a relationship and querying it as a join set of entities:
var results = database.SimpleA
.Join(database.SimpleB,
a => a.ID,
b => b.Post_ID, /
(a, b) => new { colA = a, colB = b })
.Select new SimpleA(){
Property1 = a.Col1,
Property2 = b.Col3,
Property4 = a.Col2
}).ToList();
This is only mostly functional as a starting point. You might need a left outer join instead.
Another option, if A and B have a fk constraint in the database, then you may use Navigation properties instead of a join.
If for whatever reason, your loop is required we can try and breakdown the issue:
foreach (var a in simpleA)
{
foreach (var b in simpleB) // There is no relationship here!
{
var c = new simpleC();
c.simpleAId = a.Id;
c.simpleAName = a.Name;
c.simpleBName = b.Name;
someList.Add(c);
}
}
You could try using the index, but that is very likely to cause issues.
Instead:
foreach (var a in simpleA)
{
var matchedB = simpleB.Where(x => x.Id == a.Id).FirstOrDefault();
var c = new simpleC();
c.simpleAId = a.Id;
c.simpleAName = a.Name;
c.simpleBName = matchedB.Name;
someList.Add(c);
}
I think, if I'm understanding your question, is that you don't want it to loop through in a nested fashion, but only loop once. To do that you'd do it like this.
for(int i = 0; i < simpleA.Count; i++)
{
var c = new simpleC();
c.simpleAId = simpleA[i].Name;
c.simpleAName = simpleA[i].Name;
c.simpleBName = simpleB[i].Name;
someList.Add(c);
}
I am trying to get every 5 "NewNumber" int's to insert in to var q. Let's say there are 20 records returned by UniqueNumbers, I would like to get 1-5, 6-10, 11-15, 16-20 and then have Number1 = 1,Number2 = 2,Number3 = 3,Number4 = 4,Number5 = 5 passed to var q the first time, followed by Number1 = 6, Number2 = 7, Number3 = 8, Number4 = 9, Number5 = 10 and so on...
var UniqueNumbers =
from t in Numbers
group t by new { t.Id } into g
select new
{
NewNumber = g.Key.Id,
};
UniqueNumbers.Skip(0).Take(5)
var q = new SolrQueryInList("NewNumber1", "NewNumber2","NewNumber3","NewNumber4","NewNumber5");
If you have a list of items, you can easily separate them into groups of five like this:
int count = 0;
var groupsOfFive =
from t in remaining
group t by count++ / 5 into g
select new { Key=g.Key, Numbers = g };
And then:
foreach (var g in groupsOfFive)
{
var parms = g.Numbers.Select(n => n.ToString()).ToArray();
var q = new SolrQueryInList(parms[0], parms[1], parms[2], parms[3], parms[4]);
}
I think what you want is some variation on that.
Edit
Another way to do it, if for some reason you don't want to do the grouping, would be:
var items = remaining.Select(n => n.ToString()).ToArray();
for (int current = 0; current < remaining.Length; remaining += 5)
{
var q = new SolrQueryInList(
items[current],
items[current+1],
items[current+2],
items[current+3],
items[current+4]);
}
Both of these assume that the number of items is evenly divisible by 5. If it's not, you have to handle the possibility of not enough parameters.
Try something like this:
for (int i = 0; i < UniqueNumbers.Count / 5; i++)
{
// Gets the next 5 numbers
var group = UniqueNumbers.Skip(i * 5).Take(5);
// Convert the numbers to strings
var stringNumbers = group.Select(n => n.ToString()).ToList();
// Pass the numbers into the method
var q = new SolrQueryInList(stringNumbers[0], stringNumbers[1], ...
}
You'll have to figure out how to manage boundary conditions, like if UniqueNumbers.Count is not divisible by 5. You might also be able to modify SolrQueryInList to take a list of numbers so that you don't have to index into the list 5 times for that call.
EDIT:
Jim Mischel pointed out that looping over a Skip operation gets expensive fast. Here's a variant that keeps your place, rather than starting at the beginning of the list every time:
var remaining = UniqueNumbers;
while(remaining.Any())
{
// Gets the next 5 numbers
var group = remaining.Take(5);
// Convert the numbers to strings
var stringNumbers = group.Select(n => n.ToString()).ToList();
// Pass the numbers into the method
var q = new SolrQueryInList(stringNumbers[0], stringNumbers[1], ...
// Update the starting spot
remaining = remaining.Skip(5);
}
I have class like:
class SortNode
{
public Int32 m_valRating = 0;
public SortNode(Int32 valRating)
{
this.m_valRating = valRating;
}
}
and some list refSortNodeList:
List<SortNode> refSortNodeList = new List<SortNode>();
Random refRandom = new Random();
for (int i = 0; i < 100; ++i)
{
refSortNodeList.Add(new SortNode(refRandom.Next(-10, 30)));
}
foreach (var varSortNode in refSortNodeList)
{
Console.WriteLine("SortNode rating is {0}", varSortNode.m_valRating);
}
How to sort easily my refSortNodeList by m_valRating field? Or maybe I need to use some another List class?
list.Sort((x,y) =>
x.m_valRating.CompareTo(y.m_valRating));
In-place:
refSortNodeList.Sort(
(x, y) =>
x == null ? (y == null ? 0 : -1)
: (y == null ? 1 : x.m_valRating.CompareTo(y.m_valRating))
);
Creating a new enumeration:
var newEnum = refSortNodeList.OrderBy(x => x.m_valRating);
Creating a new list:
var newList = refSortNodeList.OrderBy(x => x.m_valRating).ToList();
In-place is fastest and most memory efficient, but no good if you want to also retain the old list.
The next is faster than the last and gives results as they go, but you have to re-do the sort to use it again, in which case the third is the one to go for.
Use Linq order by.
var mySortedList = refSortNodeList.OrderBy(x => x.m_valRating);
Here is a real live example where I am pulling a list from a database but it is exactly the same concept.
vendorProducts = (from vp in db.COMPANIES_VND_PRODUCTS
join p in db.CT_CT_INV_CLASSES on vp.CLASS_ID equals p.CLASS_ID
join m in db.CT_CT_MODALITY_CODES on vp.MODALITY_ID equals m.MODALITY_ID
where vp.COMPANY_ID == companyId
select new ProductTypeModality
{
Active = p.ACTIVE.Equals("Y") ? true : false,
BioMedImaging = p.BIOMED_IMAGING,
Code = p.CLASS_CODE,
Description = p.DESCRIPTION,
Id = p.CLASS_ID,
PricingMargin = p.PRICING_MARGIN,
ModalityCode = m.MODALITY_CODE,
ModalityId = m.MODALITY_ID,
VendorId = companyId
}).OrderBy(x => x.Code).ToList<ProductTypeModality>();
Implement IComparable<T>
You can use Linq for basic sorts:
refSortNodeList.OrderBy(n => n.m_valRating);
If you need more complex sorting your will need to implement IComparable to use the built in sorting.
Try this:
refSortNodeList.Sort(new delgate(SortNode x, SortNode y)
{
return x.CompareTo(y);
}
);
It's easy using linq:
var newlist = refSortNodeList.sort( n => n.m_valRating );
List<SortNode> refSortNodeList = new List<SortNode> ();
Random refRandom = new Random ();
for (int i = 0; i < 100; ++i) {
refSortNodeList.Add (new SortNode (refRandom.Next (-10, 30)));
}
// Use this (Linq) if you're using .NET 3.5 or above.
var sortedList = refSortNodeList.OrderBy (node => node.m_valRating);
foreach (var varSortNode in sortedList) {
Console.WriteLine ("SortNode rating is {0}", varSortNode.m_valRating);
}
// Use this otherwise (e.g. .NET 2.0)
refSortNodeList.Sort (
delegate (SortNode n1, SortNode n2) {
return n1.m_valRating.CompareTo (n2.m_valRating);
}
);
foreach (var varSortNode in refSortNodeList) {
Console.WriteLine ("SortNode rating is {0}", varSortNode.m_valRating);
}
I have list of int A,B. i like to do the following step in linq
list<int> c = new List<int>();
for (int i = 0; i < a.count; i++)
{
for (int j = 0; j < b.count; j++)
{
if (a[i] == b[j])
{
c.add(a[i]);
}
}
}
if its a and b is object , I need check particular properties like this manner and add list if it equals how can i do this in linq?
You could use the Intersect method:
var c = a.Intersect(b);
This return all values both in a and b. However, position of the item in the list isn't taken into account.
You can use Intersect:
var a = new List<int>();
var b = new List<int>();
var c = a.Intersect(b);
Produce a list c containing all elements that are present in both lists a and b:
List<int> c = a.Intersect(b).ToList();
The LINQ equivalent of your code is:
var c = from i in Enumerable.Range(0, a.Count)
from j in Enumerable.Range(0, b.Count)
where a[i] == b[j]
select a[i];
var cList = c.ToList();
But it's much nicer to do:
var c = from aItem in a
join bItem in b on aItem equals bItem
select aItem;
var cList = c.ToList();
But this doesn't filter duplicates. To filter duplicates completely, you can do:
var cList = a.Intersect(b).ToList();
If you want duplicates to show up as many times as they do in b, for example:
var aSet = new HashSet<int>(a);
var cList = b.Where(aSet.Contains)
.ToList();
This is my version of intersection:
var a = new List<int>();
var b = new List<int>();
// intersection
var c = a.Where(x => b.Any(y => x == y)).ToList();
As Chris mentions in his comment on the original question, the sample code provided will return duplicates in list c (see his comment for details). Intersect will only return distinct values. To duplicate the behavior of the original sample code, try this:
var c = (from value in a
where b.Contains(a)
select a);
I have a query that sums and aggregates alot of data something like this:
var anonType = from x in collection
let Cars = collection.Where(c=>c.Code == "Cars")
let Trucks = collection.Where(c=>c.Code == "Trucks")
select new {
Total = collection.Sum(v=>v.Amount),
CarValue = Cars.Sum(v=>v.Amout),
TruckValue = Trucks.Sum(v=>v.Amount),
CarCount = Cars.Count(),
TruckCount = Trucks.Count()
};
I find it really weird that I have to declare the range variable x, especially if I'm not using it. So, am I doing something wrong or is there a different format I should be following?
I could be wrong, but from your usage, I don't think you want to do a traditional query expression syntax query with your collection anyway, as it appears you are only looking for aggregates. The way you have it written, you would be pulling multiple copies of the aggregated data because you're doing it for each of the items in the collection. If you wished, you could split your query like this (sample properties thrown in)
var values = collection.Where(c => c.Code == "A");
var anonType = new
{
Sum = values.Sum(v => v.Amount),
MinimumStartDate = values.Min(v => v.StartDate),
Count = values.Count()
};
You declare a range variable no matter the looping construct:
foreach(var x in collection)
or
for(var index = 0; index < collection.Count; index++)
or
var index = 0;
while(index < collection.Count)
{
//...
index++;
}
Queries are no different. Just don't use the variable, it doesn't hurt anything.
So, am I doing something wrong?
Your query is not good. For each element in the collection, you are enumerating the collection 5 times (cost = 5*n^2).
Is there a different format I should be following?
You could get away with enumerating the collection 5 times (cost = 5n).
IEnumerable<X> cars = collection.Where(c => c.Code == "Cars");
IEnumerable<X> trucks = collection.Where(c => c.Code == "Trucks");
var myTotals = new
{
Total = collection.Sum(v => v.Amount),
CarValue = cars.Sum(v => v.Amount),
TruckValue = trucks.Sum(v => v.Amount,
CarCount = cars.Count(),
TruckCount = trucks.Count()
};