keeping all result in a single list in linq C#? - c#

Using the simple example below,I aim to keep linq results within same list:
for (int j = 0; j < YatakList.Count; j++)
{
if (YatakList[j].GrupId != Op.yatakGrupId)
{
continue;
}
var AllBlanks = YatakList[j].blanks
.SelectMany((item, index) =>
item.Select(entry => new
{
Index = index,
Start = entry.Key,
Length = entry.Value,
Id = YatakList[j].Id,
GrupId = YatakList[j].GrupId
}))
.OrderBy(item => item.Start);
var LenghtSuitingBlanks = from blank in AllBlanks
where (blank.Length >= Op.sure)
select blank;
var closestDiff = LenghtSuitingBlanks.First();
}
By using for loop I get first result from YatakList,but within second case (j=1) of for loop altought I get the second result set I am loosing the first one.
My Question is :
How can I keep the result set of linq in a list
OR
Is there a alternative way (preferred solution) that does not use for loop

I solved the problem by crating an class named UygunYatak then by the help of another loop collect all elements in a List.
for (int i = 0; i < YatakList.Count; i++)
{
if (YatakList[i].GrupId != Op.yatakGrupId)
{
continue;
}
var AllBlanks = YatakList[i].blanks.SelectMany((item, index) => item.Select(entry => new { Index = index, Start = entry.Key, Length = entry.Value, Id = YatakList[i].Id, GrupId = YatakList[i].GrupId })).OrderBy(item => item.Start);
var LenghtSuitingBlanks = from blank in AllBlanks where (blank.Length >= Op.sure) orderby blank.Start select blank;
for (int j = 0; j < LenghtSuitingBlanks.Count(); j++)
{
UygunYatak uygunYatak = new UygunYatak();
uygunYatak.Id = LenghtSuitingBlanks.ElementAt(j).Id;
uygunYatak.GrupId = LenghtSuitingBlanks.ElementAt(j).GrupId;
uygunYatak.Start = LenghtSuitingBlanks.ElementAt(j).Start;
uygunYatak.Length = LenghtSuitingBlanks.ElementAt(j).Length;
UygunYatakList.Add(uygunYatak);
}
}
public class UygunYatak
{
public int Id;
public int GrupId;
public int Start;
public int Length;
}

Related

Reduce execution time c# algorithm

I'm solving Kattis' bokforing problem and one of the test cases fails due to execution time being too long (> 2 sec). Can anyone give me any advice on how I can improve?
class Program
{
static void Main(string[] args)
{
/* Inputs
3 5
SET 1 7
PRINT 1
PRINT 2
RESTART 33
PRINT 1
*/
string first = Console.ReadLine();
int N = Convert.ToInt32(first.Split(" ")[0]);
int Q = Convert.ToInt32(first.Split(" ")[1]);
int[] Accounts = new int[N];
string[] Operations = new string[Q];
for (int i = 0; i < Operations.Length; i++)
{
Operations[i] = Console.ReadLine();
}
for (int i = 0; i < Operations.Length; i++)
{
string[] op = Operations[i].Split(" ");
string operation = op[0];
int accountId = 0;
int ammont = 0;
if (operation == "SET")
{
accountId = Convert.ToInt32(op[1]);
ammont = Convert.ToInt16(op[2]);
Accounts[accountId - 1] = ammont;
}
if (operation == "PRINT")
{
accountId = Convert.ToInt32(op[1]);
Console.WriteLine(Accounts[accountId - 1]);
}
if (operation == "RESTART")
{
ammont = Convert.ToInt16(op[1]);
for (int j = 0; j <= N - 1; j++)
{
Accounts[j] = ammont;
}
}
}
}
}
First of all I copied recommended IO classes from FAQ to the solution, removed double loop (there is no need to loop twice - reading inputs first and then processing them) and then the main trick was to use Dictionary instead of array so there is no need to manually clear it/set amount to all items in it every time:
var scanner = new Scanner();
using(var writer = new BufferedStdoutWriter())
{
var N = scanner.NextInt();
var Q = scanner.NextInt();
var amount = 0;
var Accounts = new Dictionary<int, int>();
for (var i = 0; i < Q; i++)
{
var s = scanner.Next();
var accountId = 0;
if (s == "SET")
{
accountId = scanner.NextInt();
Accounts[accountId] = scanner.NextInt();
}
else if (s == "PRINT")
{
accountId = scanner.NextInt();
if (!Accounts.TryGetValue(accountId, out var value))
{
value = amount;
}
writer.WriteLine(value);
}
else if (s == "RESTART")
{
amount = scanner.NextInt();
Accounts = new Dictionary<int, int>();
}
}
}

Searching list by LastIndex in loop.

I am trying to complete an algorithm that adds ProcTime to a max of two other max values (JobNumMax and WSMax). I am having trouble using the FindLastIndex and FindLast in my loops.
Here is my code.
public class JobListOrder
{
public int JobNum { get; set; }
public string Workstation { get; set; }
public int Sequence { get; set; }
public int ProcTime { get; set; }
public int EndHour { get; set; }
public DateTime DueDate { get; set; }
public int Priority { get; set; }
}
Putting into list.
//New List
List<JobListOrder> list = new List<JobListOrder>();
using (StreamReader sr = new StreamReader("C:\\Users\\Nathan\\Documents\\Visual Studio 2013\\Projects\\PubsExample\\PubsExample\\JobsList.txt"))
{
//Add .txt to List
while (sr.Peek() >= 0)
{
string str;
string [] strArray;
str = sr.ReadLine();
strArray = str.Split(',');
JobListOrder currentjob = new JobListOrder();
currentjob.JobNum = int.Parse(strArray[0]);
currentjob.Workstation = strArray[1];
currentjob.Sequence = int.Parse(strArray[2]);
currentjob.ProcTime = int.Parse(strArray[3]);
currentjob.EndHour = int.Parse(strArray[4]);
currentjob.DueDate = DateTime.Parse(strArray[5]);
currentjob.Priority = int.Parse(strArray[6]);
list.Add(currentjob);
}
Sort into a particular way to start calculations
//Job Sort
var ListSort = from jobsort in list
orderby jobsort.Sequence ascending, jobsort.Priority descending, jobsort.DueDate ascending, jobsort.JobNum ascending
select jobsort;
List<JobListOrder> SortList = new List<JobListOrder>(ListSort);
Here is a slight attempt at it
//foreach (var i in SortList)
//{
// if (JobNumMax >= WSMax)
// {
// return i.EndHour = JobNumMax + i.ProcTime;
// }
// else
// return i.EndHour = WSMax + currentjob.ProcTime;
// for (var j = 0; j < SortList.Count; j++)
// {
// int JobLNumMaxIndex = SortList.FindLastIndex(i.JobNum)
// int JobNumMax = i.EndHour[JobNumMaxIndex];
// for (var k = 0; k < SortList.Count; k++)
// {
// int WSMaxIndex = SortList.FindLastIndex(i.Workstation);
// int WSMax = i.EndHour[JobNumMaxIndex];
// }
// }
//}
I am trying to find the LastIndex of a query and return a value of that particular index. I'll try to explain what I mean in the code below Searching for JobNum = 1 and Workstation = Milling with a ProcTime of 1
foreach (var i in SortList) //Iterate through SortList
{
if (JobNumMax (3) >= WSMax (4))
{
return i.EndHour = JobNumMax (3) + i.ProcTime (1); //assigns calculation to EndHour of current record
}
else
return i.EndHour = WSMax (4) + i.ProcTime (1);
for (var j = 0; j < SortList.Count; j++)
{
int JobLNumMaxIndex = SortList.FindLastIndex(1) //Finds last record with JobNum = 1
int JobNumMax = i.EndHour[JobNumMaxIndex];//Return what EndHour is at the index from JobNumMaxIndex search// Lets say 3
for (var k = 0; k < SortList.Count; k++)
{
int WSMaxIndex = SortList.FindLastIndex(Milling);//Finds last record with Workstation = Milling
int WSMax = i.EndHour[JobNumMaxIndex];//Return what EndHour is at the index from WSMaxIndex search// Lets say 4
}
}
}
Result would be 4 + 1 = 5.
I am having trouble with syntax of the algorithm. I can't get the FindLast to work at all.
It looks like you might just be having trouble with the LINQ syntax.
FindLastIndex will take a Predicate<JobListOrder> as an argument, i.e, a function which takes a JobListOrder as an input an returns true or false.
So instead of SortList.FindLastIndex(i.JobNum) you should probably have something like:
SortList.FindLastIndex(order => order.JobNum == i.JobNum);
Corrected in your code:
int JobNumMax = 0;
int WSMax 0;
foreach (var i in SortList)
{
if (JobNumMax >= WSMax)
{
return i.EndHour = JobNumMax + i.ProcTime;
}
else if (JobNumMax > 0 && WSMax > 0)
{
return i.EndHour = WSMax + currentjob.ProcTime;
}
for (var j = 0; j < SortList.Count; j++)
{
int JobLNumMaxIndex = SortList.FindLastIndex(order => order.JobNum == i.JobNum);
JobNumMax = i.EndHour[JobNumMaxIndex];
for (var k = 0; k < SortList.Count; k++)
{
int WSMaxIndex = SortList.FindLastIndex(order => order.Workstation == i.Workstation);
WSMax = i.EndHour[JobNumMaxIndex];
}
}
}

Getting position in a list and comparasion

I am trying to get positions in a list of some values to compare them with another list.
for (int i = 0; i <= commands.ToArray().Length; i++)
{
levensheteinvalues_commands.Add(commands.ToArray()[i].ToString());
levensheteinvalues_numbers.Add(
Program.ComputeLevenshteinDistance(args[0],
commands.ToArray()[i].ToString()));
}
for (int i = 0; i <= commands.ToArray().Length; i++)
{
if (smallestlevensheteinvalue == 0)
{
smallestlevensheteinvalue = levensheteinvalues_numbers[i];
}
else if (smallestlevensheteinvalue > levensheteinvalues_numbers[i])
{
smallestlevensheteinvalue = levensheteinvalues_numbers[i];
}
}
var indexes = levensheteinvalues_numbers.GetIndexes(smallestlevensheteinvalue);
Why doesn't
var indexes = levensheteinvalues_numbers.GetIndexes(smallestlevensheteinvalue);
work? And when I get the value how can I compare it to another list?
The code you have posted have some serious problems. This May solve your problem since your code as well as your approach is very unclear and ambiguous. I have blindly edited the code to fix the serious problems.
for (int i = 0; i < commands.Count(); i++) {
levensheteinvalues_commands.Add(commands.ElementAt(i).ToString());
Program.ComputeLevenshteinDistance(args[0], commands.ElementAt(i).ToString()));
}
for (int i = 0; i < commands.Count(); i++) {
if (smallestlevensheteinvalue == 0)
{
smallestlevensheteinvalue = levensheteinvalues_numbers[i];
}
else if (smallestlevensheteinvalue > levensheteinvalues_numbers[i])
{
smallestlevensheteinvalue = levensheteinvalues_numbers[i];
}
}
int index = levensheteinvalues_numbers.IndexOf(levensheteinvalues_numbers.Min());

search equals width LINQ

I have a generic list of lists, trying to determine if there are already five equal numbers in each list.
If not find equals in lists, then add list into lists
this code work but I like learn more about linq.
how can do this using LINQ.
thank you
private void button2_Click(object sender, EventArgs e)
{
int n1 = (int)numericUpDown1.Value;
int n2 = (int)numericUpDown2.Value;
int n3 = (int)numericUpDown3.Value;
int n4 = (int)numericUpDown4.Value;
int n5 = (int)numericUpDown5.Value;
int n6 = (int)numericUpDown6.Value;
int n7 = (int)numericUpDown7.Value;
int n8 = (int)numericUpDown8.Value;
int n9 = (int)numericUpDown9.Value;
int n10 = (int)numericUpDown10.Value;
int n11 = (int)numericUpDown11.Value;
int n12 = (int)numericUpDown12.Value;
list = new List<int>();
list.Add(n1);
list.Add(n2);
list.Add(n3);
list.Add(n4);
list.Add(n5);
list.Add(n6);
list.Add(n7);
list.Add(n8);
list.Add(n9);
list.Add(n10);
list.Add(n11);
list.Add(n12);
if (data.Count == 0)
data.Add(list);
else
{
int l = data.Count;
bool eq =false;
for (int i = 0; i < l; i++)
{
int count = 0;
foreach (int n in list)
{
if (data[i].IndexOf(n) != -1)
++count;
if (count == 5)
{
eq = true;
break;
}
}
if (eq == true)
break;
}
if (eq == false)
data.Add(list);
else
{
// do nothing
}
}
}
you could use Intersect and Count extension methods.
something like
var exist = false;
foreach (var existingList in data) {
if (existingList.Intersect(list).Count() >=5) {
exist = true;
break;
}
if (!exist) data.Add(list);
But depending on the size of your lists, this will be far less performant, as the "check for intersects >= 5" will intersect all data of the lists.
trying to determine if there are already five equal numbers in each list. If not, then add them into lists
You can combine Enumerable.Count and loops, for example:
int n1 = (int)numericUpDown1.Value;
foreach(List<int> list in data)
{
int count = list.Count(i => i == n1);
while(count++ < 5)
list.Add(n1);
}
[EDIT] - please see the [UPDATE] below
I believe that your current code should look like:
...
int count = 0;
for (int i = 0; i < l; i++)
{
//int count = 0;
foreach (int n in list)
{
...
Anyway, to answer your question (if I understood correctly what you want to achieve) you may use this:
class Program
{
static List<List<int>> data;
static List<int> list;
static void Main(string[] args)
{
data = new List<List<int>>();
for (int i = 0; i < 6; i++)
{
list = new List<int>();
list.Add(1);
list.Add(2);
list.Add(1);
var result = data
.Union(new[]{list})
.SelectMany(j => j)
.GroupBy(j => j)
.Select(j => new { j.Key, j })
.Where(j => j.j.Count() > 4);
if (result.Count() == 0)
data.Add(list);
}
}
}
[UPDATE]
Ok, I think I understood what you want to achieve: if there are no other lists in data that have at least 5 elements in common with the list, the list should be added to the data, which is a List<List<int>>.
var result = data.Any(i => i.Intersect(list).Count() > 4);
if(!result)
data.Add(list);
Given your code you've posted, I think the solution is:
List<int> list = new List<int>();
List<List<int>> data = new List<List<int>>();
if (data.All(l => l.Intersect(list).Count() < 5))
data.Add(list);

How to get the most common value in an Int array? (C#)

How to get the most common value in an Int array using C#
eg: Array has the following values: 1, 1, 1, 2
Ans should be 1
var query = (from item in array
group item by item into g
orderby g.Count() descending
select new { Item = g.Key, Count = g.Count() }).First();
For just the value and not the count, you can do
var query = (from item in array
group item by item into g
orderby g.Count() descending
select g.Key).First();
Lambda version on the second:
var query = array.GroupBy(item => item).OrderByDescending(g => g.Count()).Select(g => g.Key).First();
Some old fashioned efficient looping:
var cnt = new Dictionary<int, int>();
foreach (int value in theArray) {
if (cnt.ContainsKey(value)) {
cnt[value]++;
} else {
cnt.Add(value, 1);
}
}
int mostCommonValue = 0;
int highestCount = 0;
foreach (KeyValuePair<int, int> pair in cnt) {
if (pair.Value > highestCount) {
mostCommonValue = pair.Key;
highestCount = pair.Value;
}
}
Now mostCommonValue contains the most common value, and highestCount contains how many times it occured.
I know this post is old, but someone asked me the inverse of this question today.
LINQ Grouping
sourceArray.GroupBy(value => value).OrderByDescending(group => group.Count()).First().First();
Temp Collection, similar to Guffa's:
var counts = new Dictionary<int, int>();
foreach (var i in sourceArray)
{
if (!counts.ContainsKey(i)) { counts.Add(i, 0); }
counts[i]++;
}
return counts.OrderByDescending(kv => kv.Value).First().Key;
public static int get_occure(int[] a)
{
int[] arr = a;
int c = 1, maxcount = 1, maxvalue = 0;
int result = 0;
for (int i = 0; i < arr.Length; i++)
{
maxvalue = arr[i];
for (int j = 0; j <arr.Length; j++)
{
if (maxvalue == arr[j] && j != i)
{
c++;
if (c > maxcount)
{
maxcount = c;
result = arr[i];
}
}
else
{
c=1;
}
}
}
return result;
}
Maybe O(n log n), but fast:
sort the array a[n]
// assuming n > 0
int iBest = -1; // index of first number in most popular subset
int nBest = -1; // popularity of most popular number
// for each subset of numbers
for(int i = 0; i < n; ){
int ii = i; // ii = index of first number in subset
int nn = 0; // nn = count of numbers in subset
// for each number in subset, count it
for (; i < n && a[i]==a[ii]; i++, nn++ ){}
// if the subset has more numbers than the best so far
// remember it as the new best
if (nBest < nn){nBest = nn; iBest = ii;}
}
// print the most popular value and how popular it is
print a[iBest], nBest
Yet another solution with linq:
static int[] GetMostCommonIntegers(int[] nums)
{
return nums
.ToLookup(n => n)
.ToLookup(l => l.Count(), l => l.Key)
.OrderBy(l => l.Key)
.Last()
.ToArray();
}
This solution can handle case when several numbers have the same number of occurences:
[1,4,5,7,1] => [1]
[1,1,2,2,3,4,5] => [1,2]
[6,6,6,2,2,1] => [6]

Categories