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();
Related
var newList = data.GroupBy(x => new { x.Symbol })
.Select
(
x =>
{
var subList = x.OrderBy(y => y.Date).ToList();
return subList.Select((y, idx) => new
{
Symbol = y.Symbol,
Close = y.Close,
Date = y.Date,
/*p = (idx < 1) ? null : subList.Skip(idx - 1)
.Take(2).Select(o => o.Close).ToList()*/,
Vol = (idx < 1) ? 0 : new DescriptiveStatistics
(subList.Skip(idx - 1).Take(2).Select(o => (double)o.Close/(double)
subList.ElementAt(idx - 1).Close).ToList()).StandardDeviation,
});
}
)
.SelectMany(x => x)
.ToList();
I want create a variable p = (idx < 1) ? null : subList.Skip(idx - 1).Take(2).Select(o => o.Close).ToList() with the same index idx of Vol but do not appear in the return just a temporary variable(but have to use the synchronous idx as Vol). So where to write down this p or how to change the syntax
You can hold a temp variable, just like you have done with subList although I dont have a test structure to build against something like this below should work.
var newList = data.GroupBy(x => new { x.Symbol })
.Select
(
x =>
{
var subList = x.OrderBy(y => y.Date).ToList();
return subList.Select((y, idx) => { //return is a function not an object
var p = (idx < 1) ? null : subList.Skip(idx - 1).Take(2).Select(o => o.Close).ToList(); //your p
return new //this return returns the object definition
{
Symbol = y.Symbol,
Close = y.Close,
Date = y.Date,
Vol = p == null ? 0 : new DescriptiveStatistics(subList.Skip(idx - 1).Take(2).Select(o => (double)o.Close / (double)subList.ElementAt(idx - 1).Close).ToList()).StandardDeviation,
};
});
}
)
.SelectMany(x => x)
.ToList();
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 using this code to get item index in listbox:
string searchfor = "B";
for (int i = 0; i < listBox1.Items.Count; i++)
{
listBox1.SelectedIndex = i;
if (searchfor == listBox1.Text)
Console.WriteLine(listBox1.SelectedIndex);
}
List items:
A
B => 1
F
E
R
B => 5
Y
B => 7
G
B => 8
Can anyone help me to do it with linq?
You can use the overload of Select that includes the item's index:
listBox1.Items
.Select((item, index) => new {item, index})
.Where(ix => ix.item == searchFor)
.Select(ix => ix.index);
string searchfor = "B";
var Items = listbox1.Items.Where( item => item.Text == searchfor);
//in case there are more than 1
Items.ForEach( i => Console.WriteLine(i.SelectedIndex))
or
string searchfor = "B";
var Item = listbox1.Items.FirstOrDefault( item => item.Text == searchfor);
Console.WriteLine(Item.SelectedIndex);
this should work as well:
listBox1.Items.Where(item=> item.Text == searchfor)
.ForEach(i => Console.WriteLine(listBox1.Items.IndexOf(i)));
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
I have an array of 2000 strings. The strings are: "art", "economy", "sport" and "politic". I want to group each 500 elements and get their counts
Could anyone help please?
Another solution:
var count = 0;
var dictionaries =
strings.GroupBy(s => count++ / 500)
.Select(g => g.Distinct().ToDictionary(k => k, k => g.Count(s => s == k)))
.ToList();
This will create a List<Dictionary<string, int>>. Each dictionary represents a tally of 500 elements (or possibly less for the last dictionary), where the keys are strings and the values are the number of occurrences of the string among the 500 elements the dictionary represents.
There is no requirement to hardcode all the possible values that may be encountered.
For the maximum possible performance you can also use this version:
var count = 0;
var dictionaries =
strings.GroupBy(s => count++ / 500)
.Select(g => g.Aggregate(
new Dictionary<string, int>(),
(d, w) => { d[w] = (d.ContainsKey(w) ? d[w] + 1 : 1); return d; })
)
.ToList();
This version iterates over each element in your source array exactly once. The output is in the same format as the first version.
var result = strings.Select((s, i) => new { s, i })
.GroupBy(x => x.i / 500)
.Select(x => x.GroupBy(y => y.s)
.Select(z => new {
Name=z.Key,
Count=z.Count()
}).ToList())
.ToList();
Try
var grouping = Enumerable.Range(0,2000)
.Select(i => i / 500)
.Zip(Strings, (i,s) => new { Group = i, Str = s})
.GroupBy(anon => anon.Group,
anon => anon.Str,
(key,g) => new
{
Key = key,
Art = g.Count(str => str == "art"),
Economy = g.Count(str => str == "economy"),
Politic = g.Count(str => str == "politic"),
Sport= g.Count(str => str == "sport")
});
foreach(anon in grouping)
{
//textbox logic OP will have to change to suit
TextBox1.WriteLine(String.Format("Group: {0}", anon.Key));
TextBox1.WriteLine(String.Format("Art: {0}",anon.Art));
TextBox1.WriteLine(String.Format("Economy: {0}",anon.Economy ));
TextBox1.WriteLine(String.Format("Politic: {0}",anon.Politic ));
TextBox1.WriteLine(String.Format("Sport: {0}",anon.Sport));
}
Alternatively (as per Snowbear)
var grouping = Strings.Select((s,i) => new { Group = i / 500, Str = s})
.GroupBy(anon => anon.Group,
anon => anon.Str,
(key,g) => new
{
Key = key,
Art = g.Count(str => str == "art"),
Economy = g.Count(str => str == "economy"),
Politic = g.Count(str => str == "politic"),
Sport= g.Count(str => str == "sport")
});
foreach(anon in grouping)
{
//textbox logic OP will have to change to suit
TextBox1.WriteLine(String.Format("Group: {0}",anon.Key + 1));
TextBox1.WriteLine(String.Format("Art: {0}",anon.Art));
TextBox1.WriteLine(String.Format("Economy: {0}",anon.Economy ));
TextBox1.WriteLine(String.Format("Politic: {0}",anon.Politic ));
TextBox1.WriteLine(String.Format("Sport: {0}",anon.Sport));
}
int CountElementsInGroup = 500;
//from 500 to 1000
int NumberGroup = 2;
string[] GroupTypes = new string[4] { "art", "economy", "sport", "politic" };
//Fill example array
string[] arr = new string[2000];
Random rand = new Random();
for (int i = 0; i < arr.Length;i++ )
arr[i] = GroupTypes[rand.Next(0, 3)];
var res = (from p in arr.Skip((NumberGroup - 1) * CountElementsInGroup).Take(CountElementsInGroup)
group p by p into g
select new GroupCountClass { GroupName = g.Key, GroupCount = g.Count() });
textBox1.Text = "";
foreach (GroupCountClass c in res)
{
textBox1.Text += String.Format("GroupName:{0} Count:{1};",c.GroupName,c.GroupCount);
}