I have data like this
data
1 1 2 2 2 2 2 blank/ null 1 1 3 3 4 4 4 blank/ null blank/ null
Trying to get the base (total non blank rows) and percent column along with frequency.
So far Achieved to get this
Column Count
1 4
2 5
3 2
4 3
With this code
var result = data.GroupBy(x => x.Field<string>(xx), (row, l) => new Group { Column = row, Count = l.Count() })
I am trying groupby to get output something like this
Column Count Base Percent
1 4 14 28.57142857
2 5 14 35.71428571
3 2 14 14.28571429
4 3 14 21.42857143
Steps
Filter out unwanted entries (nulls)
Get the total count
Group your data
Project the data to your desired result
Like this
var data = new int?[] { 1, 1, 2, 2, 2, 2, 2, null, 1, 1, 3, 3, 4, 4, 4, null, null };
var filteredData = data.Where(x => x != null);
var totalCount = filteredData.Count();
var groups = filteredData.GroupBy(x => x);
var result = groups.Select(x => new { Value = x.Key, Count = x.Count(), Percent = x.Count() * 100.0 / totalCount });
Note: a group is a collection of the grouped items plus a key. The key is whatever your chose to group by. In this example, the key is an int. And because the group is a collection you can do stuff like .Count() on it.
Related
How do I select an int[] to as a column of a EF-to-SQL query? Suppose I have another column, and I would like to count the number of times these numbers appear... result would look something like this:
int[] nos = { 1, 2, 9, 4 };
-----------------------------------
nos | Count
1 | 2
2 | 1
9 | 3
4 | 1
If I have a column SampleColumn with values:
-----------------------------------
SampleColumn
1
1
2
3
4
5
9
11
25
9
9
Something like this as my code (I honestly don't know how to approach it so I'm guessing it's like this):
var query = db.Table.Select(a => new { nos, a.SampleColumn.Count(b => b == nos } ).ToList();
I would like to be able to change nos as I prefer. Thanks.
you can group the list.
int[] nos = { 1, 2, 9, 4 };
var result = nos.GroupBy(x => x).Select(x => new { x.Key, Count = x.Count() });
your code
var query = db.Table.GroupBy(x => x.SampleColumn).Select(x => new { x.Key, Count = x.Count() });
I am trying to figure out how to rank a list with multiple conditions:
This is my list:
Let me explain the list above:
a. 'AreaCode' is an unique ID for each group of the list.
b. I will rank the list based on highest value of Rank 1 (highlighted with yellow).
c. If Rank 1 has same value, I will find highest value of Rank 2 (highlighted by green).
d. If Rank 2 has same value, I will find highest value of Rank 3 (highlighted by blue).
e. In this case, there are same value for Rank 1 (7 and 7), so I will find the highest value for Rank 2, however the Rank 2 value also same (4 and 4), so I will find the highest value for Rank 3 (1 and 2).
f. So 'Ranking' column is the result that I want to achieve, which is a list with these value: [1, 1, 1, 3, 3, 3, 2, 2, 2, 2, 2, 2, 1, 1, 1, 3, 3, 3].
Last time I can do but with simple scenario (there are no Rank 1, Rank 2 or Rank 3) using this code:
var rankings = myIndexList.GroupBy(x => x)
.OrderByDescending(g => g.Key)
.Select((g, i) => new { Key = g.Key, Rank = i + 1 })
.ToDictionary(x => x.Key, x => x.Rank);
var output = myIndexList.Select(x => new { Col1 = x, Rank = rankings[x] })
.ToList();
Any ideas to achieve the result on 'Ranking' column?
Thank You!
I recommend this.
public class Item
{
public string Name { get; set; }
public int Value { get; set; }
}
/////
var list = new List<(Item Col1, int Rank)>();
var nameGroup = items.GroupBy(i => i.Name);
var sorted = nameGroup.OrderBy(i => i.Key);
foreach (var group in sorted)
{
int ranking = 1;
foreach (var item in group.OrderByDescending(i => i.Value))
{
list.Add((Col1: item, Rank: ranking++));
}
}
I'm getting following data from my Stored procedure
Brand Start End
----------------------------------------
Nike 0 4
Adidas 0 5
Nike 4 10
Levis 0 3
Adidas 5 8
I want to check if there is any range data for given start and end numbers and if there is any data with given range i want to get maximum "End" number of each brand
ex: assume that i want to check whether there is any data for gap 2 to 6
in this case;
for NIKE:
NIKE has ranges 0-4 and 4-10. So its within my 2-6 range (2 is in between 0-4 and 6 is in between 4-10) So i want my result as "NIKE 10"
for ADIDAS: ADIDAS has ranges 0-5 and 5-8. So it also within 2-6 range (2 is in between 0-5 and 6 is in between 5-8) I want it as "ADIDAS 8"
for LEVIS: LEVIS has one range 0-3 and 2 is in between that range. So i want it as "LEVIS 3"
i wrote a Linq query for that and i want to make sure that it's working fine.
var result = (from items in responce.List
where items.Start>= 2 && items.End <= 6
group items by items.Brand into g
select new
{
Max = g.Max(x=> x.End)
});
the result should contain;
NIKE 10
ADIDAS 8
LEVIS 3
Thanks in advance
You are almost there, took me a minute to understand what you were after, but all you need to do is treat each number in your range as an independent value.
That means the database range can have either the 2, the 6 or both between its values.
all you need to do is rewrite the linq to something like this:
var result = from item in list
where (item.Start <= 2 && item.End >= 2) || (item.Start <= 6 && item.End >= 6)
group item by item.Brand into g
select new
{
Brand = g.Key,
Max = g.Max(x => x.End)
};
The only change being
where (item.Start <= 2 && item.End >= 2) || (item.Start <= 6 && item.End >= 6)
All these does is check if any range has 2 or if any range has 6 in it.
For a complete example see this gist.
EDIT:
Try this one, it should always show the max range for the brand, if the values specified exists inside that brand:
var result = (
from item in list
group item by item.Brand into g
from subItem in g
where (subItem.Start <= 2 && subItem.End >= 2) || (subItem.Start <= 6 && subItem.End >= 6)
select new
{
Brand = g.Key,
Max = g.Max(x => x.End)
}
).Distinct();
Here's another gist with the updated linq.
Try this :
static void Main(string[] args)
{
List<Sneaker> sneakers = new List<Sneaker>() {
new Sneaker() { brand = "Nike", start = 0, end = 4},
new Sneaker() { brand = "Adidas", start = 0, end = 5},
new Sneaker() { brand = "Nike", start = 4, end = 10},
new Sneaker() { brand = "Levis", start = 0, end = 3},
new Sneaker() { brand = "Adidas", start = 5, end = 8}
};
int start = 2;
int end = 6;
var groups = sneakers.GroupBy(x => x.brand).Select(x => x.OrderBy(y => y.end)).Select(x => x.Any(y => y.end > end) ? x.FirstOrDefault(): x.LastOrDefault())
.Where(x => x != null).Select(x => new {brand = x.brand, end = x.end}).ToList();
}
I have an unsorted list of ints:
1 3 1 2 4 3 2 1
I need to sort it, and before each group of equal numbers, insert a 0:
0 1 1 1 0 2 2 0 3 3 0 4
Is there a way to get from the first list to the second list with just one LINQ statement? I'm stuck at
from num in numbers
orderby num
select num
followed by a foreach loop that manually constructs the final output based on these results. I'd like to eliminate the second loop entirely, if possible.
Try:
list.GroupBy(n => n)
.OrderBy(g => g.Key)
.SelectMany(g => new[] { 0 }.Concat(g))
For each group of numbers, prepend 0, and then flatten the list with SelectMany.
And in query syntax:
from num in list
group num by num into groupOfNums
orderby groupOfNums.Key
from n in new[] { 0 }.Concat(groupOfNums)
select n
int[] nums = { 1, 3, 1, 2, 4, 3 ,2 ,1};
var newlist = nums.GroupBy(x => x)
.OrderBy(x=>x.Key)
.SelectMany(g => new[] { 0 }.Concat(g)).ToList();
Try this out on LinqPad.
var list = new int[]{1, 3, 1, 2, 4, 3, 2, 1};
var q = from x in list
orderby x
group x by x into xs
from y in (new int[]{0}).Concat(xs)
select y;
q.Dump();
This should give you the desired result.
I have a list using this Linq query
filterEntities = (from list in filterEntities where list.Id== 0 && list.Id== 1 && list.Id == 3 && list.Id== 6 select list).OrderBy(r => r.Id).ToList();
Now this linq returns a list like
ID Age
0 18
0 19
1 21
3 24
6 32
6 08
I want to generate a list using sum of same Id's which returns like
ID Age
0 37
1 21
3 24
6 40
Please suggest me possible query
I think you are looking to use a group by like this
List<int> ids = new List<int>() { 0, 1, 3, 6 };
filterEntities = (from list in filterEntities
where ids.Contains(list.Id)
group list by list.id into g
orderby g.Key
select new
{
ID = g.Key,
Age = g.Sum(x => x.Age),
}).ToList();
I would clean up the query like this, because the long expression looks a bit confusing:
var idList = new List<int> { 0, 1, 3, 6};
filterEntities = from e in filterEntities
where idList.Contains(e.Id)
group e by e.Id into g
select new { Id = g.Key, Sum = g.Sum(e =>e.Age) };
filterEntities = filterEntities.Where(l=>new[] { 0, 1, 3, 6 }.Contains(l.Id))
.Sum(c=>c.Age)
.GroupBy(r=>r.Id)
.ToList();