I am trying to use Aggregate function Count() on some column using dynamic linq query but I am not able to achieve, what I am exactly looking is
Select Count(Id),Id
from Table1
Group By Id
Having Count(Id) > 1
I want to convert the same query to dynamic linq query, any suggestions on how to achieve this?
Stolen from here:
var distinctItems =
from list in itemsList
group list by list.ItemCode into grouped
where grouped.Count() > 1
select grouped;
The following two queries will give you the exact same result:
first with lambda second result without.
var Table1 = new List<Row>();
for (int i = 0; i < 10; i++)
{
for (int m = 0; m < 5; m++)
{
for (int x = 0; x < i + m; x++)
{
Table1.Add(new Row() { Id = m });
}
}
}
var result = Table1.GroupBy(row => row.Id)
.Where(p => p.Count() > 1);
var resultB = from row in Table1
group row by row.Id into rowGrouped
where rowGrouped.Count() > 1
select rowGrouped;
foreach (var r in resultB)
{
Console.WriteLine("ID {0} count: {1}", r.Key, r.Count());
}
May be something like this
list.GroupBy(item => item.Id)
.Where(group => group.Count() > 1)
.Select(group => new {
Id = group.Key,
Count = group.Count() });
Related
I have Table like ProductInventory , In that I have some product with quantity .
I want select all rows where The least of a field equals to my input(number) .
I try with this :
List<product> Products = new List<product> {
new product{Id=1,Name="A",Quantity=1},
new product{Id=1,Name="A",Quantity=2},
new product{Id=1,Name="A",Quantity=3},
new product{Id=1,Name="B",Quantity=4},
new product{Id=1,Name="B",Quantity=7}
};
var result = Products
.AsEnumerable()
.GroupBy(r => r.Name)
.Where(g => (int)g.Sum(r =>r.Quantity)<= 4)
.ToList();
but it causes a return zero.
example:
I don't know is it possible in linq or not. But you can try this.
var result = Products.AsEnumerable().Where(g => g.Name == "A").ToList();
int userInput =4;
var total = 0;
var selectList = new List<product>();
for (int i = 0; i < result.Count; i++)
{
for (int j = i; j < result.Count; j++)
{
if (total + result[j].Quantity <= userInput)
{
total += result[j].Quantity;
selectList.Add(result[j]);
}
}
if (total == userInput)
break;
else
{
total = 0;
selectList = new List<product>();
}
}
if(userInput!=total)
selectList = new List<product>();
With that latest update, I think I finally understand what you are trying to do.
This won't work however, because you cant build the sum of booleans.
var result = Products
.AsEnumerable()
.GroupBy(r => r.Name)
.Where(g => g.Sum(r =>r.Quantity== 4))
.ToList();
What you actually want is
var result = Products
.GroupBy(r => r.Name)
.Where(g => g.Sum(r =>r.Quantity) >= 4) //or == 4 or whatever
.ToList();
I have a array which looks like this :-
a[53]={ARPNUM-T,
OR1PATTYP-T,
IVNUM-T,
IVDESC-T,
ORDEPT-T,
ARPNAME-T,
ARGNAME-T,
ARPATADDR1-T,
ARPATCITY-T,
ARPATSTATE-T,
ARPATZIP-N,
ARSEX-T,
ARBIRTH-N,
ARSSN-T,
ARMARRY-T,
ARADMDT-N,
ARDISDT-N,
ARPEMP-T,
ARPHY1-T,
ARPHYNM1-T,
ARMRNUM-T,
ARGUARSSN-T,
ARPHONE-T,
AREMPLYR-T,
ARADDR1-T,
ARSTATE-T,
ARZIP-N,
ARPATPHONE-N,
ARDIAG01-T,
ISSUBNAME-T,
ISCOMPCD-T,
ISCONAME-T,
ISCONTRAC-T,
ISGROUP-T,
ISPRIMARY-T,
ISCOADDR-N,
ISCOCITST-T,
ISPATREL-T,
ISCERTNO-T,
ISCOZIP-N,
ISSUBNAME-T,
ISCOMPCD-T,
ISCONAME-T,
ISCONTRAC-T,
ISGROUP-T,
ISPRIMARY-T,
ISCOADDR-N,
ISCOCITST-T,
ISPATREL-T,
ISCERTNO-T,
ISCOZIP-N,
ARCITY-T}
There are some repeated values like ISSUBNAME-T,ISCOMPCD-T.
i need to fill the array a to array b
where repeated value will be suffixed by the number of times of repetition ,
For eg - if ISSUBNAME-T is repeated 3 times then ISSUBNAME-T_3 .
I have tried a code:-
for (int d = 1; d < 53; d++)
{
b[0] = a[0];
for (int k = 1; k < d; k++)
{
int count = 0;
//b[d] = a[d];
if (a[d] == a[d - k])
{
count++;
if (count > 0)
{
b[d] = a[d] + "_" + count + "";
}
else
{
b[d] = a[d];
}
//Console.WriteLine(count);
}
//Console.WriteLine(count);
}
//Console.WriteLine(count);
}
But it's not showing correct output.
Group array items by their values. Then check if group contains more than one item. If so, then return formatted item value, otherwise simply return item value:
string[] b = a.GroupBy(i => i)
.Select(g => g.Count() > 1 ?
String.Format("{0}_{1}", g.Key, g.Count()) : g.Key)
.ToArray();
Query syntax (easily allows to calculate group length only once):
var query = from i in a
group i by i into g
let count = g.Count()
select count > 1 ? String.Format("{0}_{1}", g.Key,count) : g.Key;
string[] b = query.ToArray();
UPDATE: If you want to keep all items and have incremental suffixes
string[] b = a.GroupBy(e => e)
.SelectMany(g => g.Count() == 1 ?
g.Take(1) :
g.Select((e,i) => String.Format("{0}_{1}", e,i+1))
.ToArray();
UPDATE 2: If you want also preserving original order, then simple loop and dictionary will be simpler
string[] b = new string[a.Length];
var duplicatedItems = a.GroupBy(a => a)
.Where(g => g.Count() > 0)
.ToDictionary(g => g.Key, g => g.Count());
for(int i = b.Length - 1; i >= 0 ; i--)
{
string item = a[i];
if (!duplicatedItems.ContainsKey(item))
{
b[i] = item;
continue;
}
b[i] = String.Format("{0}_{1}", item, duplicatedItems[item]);
duplicatedItems[item]--;
}
Linq query for comparison
string[] b =
a.Select((e,i) => new { Item = e, Index = i })
.GroupBy(x => x.Item)
.SelectMany(g => g.Count() == 1 ?
g.Take(1) :
g.Select((x,i) => new {
Item = String.Format("{0}_{1}", x.Item, i+1),
Index = x.Index
}))
.OrderBy(x => x.Index)
.Select(x => x.Item)
.ToArray();
I have a datatable and I am doing operations on it to take the result like this:
var result = from row in DTgraph.AsEnumerable()
group row by row.Field<string>("Campaign") into grp
select new
{
Campaign = grp.Key,
Count = grp.Count(),
SL = grp.Sum(s => s.Field<Decimal>("Inb.ServiceLevel"))
};
I want to loop on that result
I tried these two ways:
First
for (int i=0;i< result.Count(); i++){
{
}
but I couldn't type result[i].Count
second
foreach (var item in result)
{
}
Your LINQ expression returns an IEnumerable, which cannot be accessed through an indexer. This is why result[i] in your first attempt does not work.
The fix is simple: Convert your IEnumerable to a List:
var result = (from ... select new { ... }).ToList();
var result = (from row in DTgraph.AsEnumerable()
group row by row.Field<string>("Campaign") into grp
select new
{
Campaign = grp.Key,
Count = grp.Count(),
SL = grp.Sum(s => s.Field<Decimal>("Inb.ServiceLevel"))
}).ToList();
if(result.Count() > 0)
{
///Do Something////
}
Why do you need that? Use for instead.
Anyway, if you insist, you can create an extension function that will provide this functionallity. Something like this:
public static void ForEachIndex<T>(this IEnumerable<T> collection, Action<T, int> action)
{
int index = 0;
foreach (T curr in collection)
{
action(curr, index);
index++;
}
}
Usage:
List<int> collection = new List<int> {1,2,3,4,5};
int output = 0;
collection.ForEachIndex((curr,idx) => output += curr * idx);
This question already has answers here:
How to Count Duplicates in List with LINQ
(7 answers)
Closed 9 years ago.
How can I check if there are two or more equal values in one array?
eg. in this example, i want the program to tell me that there is a pair of 2 and a pair of 4
int[] array1 = { 1, 2, 4, 2, 4 };
Using Linq
var result = array1.GroupBy(i=>i)
.Select(g=>new {Value = g.Key, Count = g.Count()})
.Where(x=>x.Count>1)
.ToList();
foreach (var pair in result)
{
Console.WriteLine("PAIR: " + pair.Value + " COUNT: " + pair.Count);
}
[EDIT] Sorry, this answers the question "How can I check if there are two or more equal values in one array?", but it doesn't tell you the actual duplicates...
This would work, but possibly it isn't the most efficient way!
int[] array1 = { 1, 2, 4, 2, 4 };
if (array1.Distinct().Count() < array1.Length)
Console.WriteLine("Contains Dupes");
If you want the most efficient approach:
bool containsDupes(int[] array)
{
for (int i = 0; i < array.Length - 1; ++i)
{
int n = array[i];
for (int j = i+1; j < array.Length; ++j)
if (array[j] == n)
return true;
}
return false;
}
I don't think you can get much more efficient than that. It will return as soon as it finds any match.
You could use a Linq Statement like:
var query =
from numbers in array1
group numbers by numbers into duplicates
where duplicates.Count() > 1
select new { Item = duplicates.Key, ItemCount = duplicates.Count() };
This will return the following:
Item 2: ItemCount 2
Item 4: ItemCount 2
Or another syntax for the same:
var query = array1.GroupBy(x => x)
.Where(x => x.Count() > 1)
.Select(x => new { x, Count = x.Count() });
You could use LINQ's GroupBy
Example:
var grouped = array1.GroupBy(x => x).Select(x => new { Value = x.Key, Count = x.Count() });
foreach(var item in grouped) {
if (item.Count == 1)
continue;
Console.WriteLine("There are {0} instances of the number {1} in the array.", item.Count, item.Value);
}
I like this syntax:
int[] array1 = { 1, 2, 4, 2, 4 };
var isThereAnyRepeated = (from i in array1
group i by i into g
where g.Count() > 1
select g).Any();
Console.WriteLine(isThereAnyRepeated);
Here's a slight variation of I4V's answer.
Instead of Select and ToList this uses ToDictionary.
using System;
using System.Linq;
namespace StackOverflow_2013_05_27_EqualValuesInArray
{
class Program
{
static void Main(string[] args)
{
int[] array = { 1, 2, 4, 2, 4 };
var tbl = array
.GroupBy(n => n)
.Where(g => g.Count() > 1)
.ToDictionary(g => g.Key, g => g.Count());
foreach (var pair in tbl)
Console.WriteLine("{0} is in array {1} times", pair.Key, pair.Value);
Console.ReadLine();
}
}
}
class item
{
int value;
int number;
}
list<item> items = new list <item>();
for(int i=0; i<array1.length;i++)
{
if (i=0)
items.add(new item(array1[i],1))
else if (array1.contains(array[i])) items.add(new item(array1[i],))
else items.add(new item(array1[i],1))
}
I want to check if under column "name" is there any same value. If yes so i want to check if the next same value > Bit + Size. I can do it with 2 for loops but what i want is something more simple.
Can anyone show me how?
My DataTable:
name Bit Size
m1 8 3
m0 9 5
m1 10 2 // Error, should be 11
m2 11 4
My code:
for(int i = 0; i <= Dt.Rows.Count - 1; i++)
{
for(int y = i +1; y <= Dt.Rows.Count - 1, y++ )
{
if(Dt.Rows[i]["name"].ToString() == Dt.Rows[y]["Name"].ToString())
if( (Convert.ToInt32(Dt.Rows[i]["Bit"].ToString()) + Convert.ToInt32(Dt.Rows[i]["Size"].ToString()) > (Convert.ToInt32(Dt.Rows[y]["Bit"].ToString()) ) )
{
// Show Error
MessageBox.Show("Error");
Dt.Rows[y]["Bit"] = Dt.Rows[i]["Bit"];
}
}
}
For what it's worth, this is the Linq approach:
var invalidGroups = DT.AsEnumerable()
.GroupBy(r => r.Field<string>("name"))
.Where(g => g.Count() > 1)
.Select(g => new { Name = g.Key, FirstRow = g.First(), Group = g })
.Select(x => new { x.Name, x.FirstRow, x.Group, FirstSum = x.FirstRow.Field<int>("Bit") + x.FirstRow.Field<int>("Size") })
.Where(x => x.Group.Any(r => x.FirstSum < r.Field<int>("Bit") + r.Field<int>("Size")));
foreach (var x in invalidGroups)
{
string name = x.Name;
DataRow referenceRow = x.FirstRow;
var invalidRows = x.Group
.Where(r => x.FirstSum < r.Field<int>("Bit") + r.Field<int>("Size"));
foreach (DataRow r in invalidRows)
{
int sum = r.Field<int>("Bit") + r.Field<int>("Size"); // 12 instead of 11
r.SetField("Bit", referenceRow.Field<int>("Bit"));
r.SetField("Size", referenceRow.Field<int>("Size"));
}
}
As you can see, it's not really shorter, but probably more maintainable or readable.
Try this in SQL
select b.name, b.bits + b.size
from Table_1 b
where exists (select name from Table_1 a where a.name = b.name group by name having count(*) > 1)
group by b.name, b.bits + b.size
having count(*) = 1