How do I write this block of code in LINQ? - c#

I need to use linq as many times as possible and I have no idea how to use linq in this type of method.
I've tried some code from certain webs however none of them worked
List<MemorableD> memorables = new List<MemorableD>();
List<StateMD> states = new List<StateMD>();
void Find(List<MemorableD> selected)
{
for (int i = 0; i < states.Count; i++)
{
for (int j = 0; j < memorables.Count; j++)
{
if (states[i].Month == memorables[j].Month && states[i].Day == memorables[j].Day)
{
MemorableD select = new MemorableD(memorables[j].Year, memorables[j].Month, memorables[j].Day, memorables[j].Event, states[i].Event);
selected.Add(select);
}
}
}
}
I need to write this add method with LINQ

Try to break down your problem. If you were to analyse your loops, you are iterating over the States and Memorables, and creating instances of MemorableD where State and Memorable have the same Month and Day and latter adding them to the List.
Translating it to Linq,
from StateMD state in states
from MemorableD memorable in memorables
where state.Month == memorable.Month && state.Day == memorable.Day
let selectValue = new MemorableD(memorable.Year, memorable.Month, memorable.Day, memorable.Event, state.Event)
select selectValue
The second part of the problem is to add it to the List called selected. You can add an IEnumerable to selected using the AddRange method.
So, combining the Linq statement with AddRange method,
selected.AddRange(from StateMD state in states
from MemorableD memorable in memorables
where state.Month == memorable.Month && state.Day == memorable.Day
let selectValue = new MemorableD(memorable.Year, memorable.Month, memorable.Day, memorable.Event, state.Event)
select selectValue);

Related

Index out of rage cannot be resolved [ASP.NET Core]

I got the following code:
//getting skills from DB
var skills = this.db.HumanSkills.Where(r => r.HumanId == model.Id).Include(x => x.Skill).ToList();
for (int i = 0; i < model.Skills.Count; i++) //iterating over the list. Boundary set to i < model.Skills.Count this is number of elements in my viewmodel (model.Skills) using which I am going to update Name property of my DB elements.
{
if (skills[i] != null) //index out of range here. Why?
{
//here I update DB skill names using model skill names
skills[i].Skill.Name = model.Skills[i].Skill.Name;
}
else //here I create new Skill for every element of the DB skill list that doesn't exist
{
var newSkill = new HumanSkill { Skill = model.Skills[i].Skill, Human = currentHuman };
this.db.Add(newSkill);
this.db.SaveChanges(); //yes, I know it's not a good practice to execute it each time, but otherwise rows in my HumanSkills table are not sorted.
}
}
On line:
if (skills[i] != null) //index out of range here. Why?
I am getting index out of range, even though I use !=null
It seems to me that var skills is a different object than model.Skills
"var skills" and "model.Skills" are 2 different variables.
There are of the same type, but it's 2 differents objects!
You can do that :
IEnumerable<Skill> skillsList = this.db.HumanSkills.Where(r => r.HumanId == model.Id).Include(x => x.Skill).ToList();
foreach (Skill s in skillsList)
{
// your logic... or debug.print for check how many items are get from the db
}

Remove non unique objects between two lists C#

I have two lists of objects and I want to remove all appearances of the 2nd lists' objects in my 1st list. Basically, get all unique values in the 1st list relative to the 2nd list (the lists themselves do not have duplicates within them). Another way to phrase this question is: how can I use List functions on my custom List. I've read around and people are suggesting overriding the Equals function, which I've done but it hasn't helped me. What I currently have:
filteredEntries and actuallyFilteredEntries are identical to start off, entries is an independent list. (I tried using actuallyFilteredEntriesas basically a copy of filteredEntries where I can remove entries or manipulate the data in other ways.
for (int i = 0; i < entries.Count; i++)
{
for (int j = 0; j < filteredEntries.Count; j++)
{
if (filteredEntries[j].Equals(entries[i]))
{
duplicateCount++;
// prints false
Console.WriteLine(actuallyFilteredEntries.Remove(filteredEntries[j]));
}
}
}
this is how I'd like it to work, but apparently you have to use the same object in the Remove() f.e. actuallyFilteredEntries.Remove(actuallyFilteredEntries[j]). The problem with this is, I run into an index out of bounds error.
I also tried a LINQ approach to no avail
var etc = actuallyFilteredEntries.Except(entries);
expected result: I'm left with a list of unique values, reality: (it saves all actuallyFilteredEntries without throwing out any entries).
I'll add my Equals() and GetHashCode() method overrides, maybe there's some mistakes in them that I didn't manage to find:
public bool Equals(Entry entry)
{
if (Object.ReferenceEquals(entry, null))
{
return false;
}
if (this.GetType() != entry.GetType())
return false;
return (Desired_due_date == entry.Desired_due_date) && (Order_number== entry.Order_number) && (Series_number == entry.Series_number)
&& (Product_name == entry.Product_name) && (Product_code == entry.Product_code) && (ProcessesID== entry.ProcessesID)
&& (Ordered_amount== entry.Ordered_amount) && (Amount_made== entry.Amount_made) && (Start_date== entry.Start_date);
}
public override int GetHashCode()
{
return this.Desired_due_date.GetHashCode() ^ this.Order_number.GetHashCode() ^ this.Series_number.GetHashCode() ^ this.Product_name.GetHashCode()
^ this.Product_code.GetHashCode() ^ this.ProcessesID.GetHashCode() ^ this.Ordered_amount.GetHashCode() ^ this.Amount_made.GetHashCode()
^ this.Start_date.GetHashCode();
}
Any help or ideas are appreciated, doesn't matter how I do it (efficiency etc), I just need a unique list out of two.
var etc = actuallyFilteredEntries.Union(entries)
The documentation for which can be found here: .Union MS Docs
Returns
IEnumerable
An IEnumerable that contains the elements from both input sequences, excluding duplicates.
Answer without LINQ:
var seen = new HashSet<T>(filteredEntries);
for (var i = 0; i < entries.Count; i++)
{
if (seen.Contains(entries[i]))
{
entries.RemoveAt(i);
i--;
}
}
With the help of the LINQ Union Operator, you can achieve it.
Please check the below code.
List<string> objList_1 = new List<string>() {"A","B","C","D" };
List<string> objList_2 = new List<string>() { "A", "B", "E", "F" };
var vUniqueList = objList_1.Intersect(objList_2).ToList();
======OutPut ============
"A"
"B"
If you want only Unique value from the two list then please check following code
var result = objList_1.Except(objList_2).Concat(objList_2.Except(objList_1)).ToList();
====Output=======
"C"
"D"
"E"
"F"

Removing list index while iterating through the list using nested loops

Hey so I'm trying to execute this bit of code, however it is going out of bounds I would assume due to it trying to execute the first loop at the index that was removed. Does anyone know a way I can execute this code without it going out of bounds?
for (int i = myList1.Count - 1; i >= 0; i--)
{
for (int j = 0; j < myList2.Count - 1; j++)
{
if (myList2[j] != myList1[i])
{
myList1.RemoveAt(i);
}
}
}
Obligitory Linq Answer:
myList1 = myList1.Where(i => !myList2.Contains(i)).ToList();
Basically, instead of looping through them both on your own, you use Linq to do it for you. You set myList1 to be the items matching the where clause of [myList2 does not contain item X].

How to properly remove all labels from form [duplicate]

Yesterday I wrote a piece of code to remove all the controls in a form that fulfills certain criteria. Writing it naively, this is what I come up with.
for (int i = 0; i < this.Controls.Count; ++i)
{
if (this.Controls[i].Name.Length == 2)
{
this.Controls.Remove(this.Controls[i);
}
}
But it so happens that the code is wrong. I then change it to:
foreach (Control ctr in this.pbBoardImage.Controls)
{
if (ctr.Length == 2)
{
this.Controls.Remove(ctr);
}
}
But it still wasn't correct.
I know that the correct way would be:
for (int i = this.Controls.Count - 1; i >= 0; i--)
{
if (this.Controls[i].Name.Length == 2)
{
this.Controls.Remove(this.Controls[i]);
}
}
However it still doesn't feel elegant. I couldn't use List.RemoveAll, since this.Controls wasn't a List. So can I ask for a more elegant way, preferably without using a loop?
Not sure why you didn't like this answer... I've highlighted the important RemoveAt; however, as an alternative in .NET 3.5/C# 3.0: LINQ:
var qry = from Control control in Controls
where control.Name.Length == 2
select control;
foreach(var control in qry.ToList()) {
Controls.Remove(control);
}
(original)
You can't Remove within foreach - it breaks the iterator. A common approach here is to iterate backwards:
for (int i = this.Controls.Count - 1; i >= 0; i--) {
if (this.Controls[i].Name.Length == 2) {
this.Controls.RemoveAt(i); // <=========== *** RemoveAt
}
}
This avoids the "off by one" issues, etc.

How do I create a Dictionary<int, EntityState>, and add values inside a for loop?

So, I hope this is simple. I'm coming up with a way to store disconnected entities (due to my case being quite peculiar), and for it to work, I'd like to create a Dictionary with those values inside a for loop.
But I'm getting "An item with the same key" has been added problem, which I do not know why.
I've tried the following:
Dictionary<int, EntityState> StateProduct = new Dictionary<int, EntityState>();
for (int s = 0; s < userProducts.Count; s++ ) //userProducts.Count had value of 3
{
StateProduct.Add(s, EntityState.Modified);
}
But I get the error:
In which:
I really really do not know what's going on..
Edit: Here is the complete code
var dbIboID = dbs.OrderDB.Where(x => x.OrderID == Order[0].OrderID).FirstOrDefault();
if(dbIboID.IboID != uid)
{
return false;
}
//2nd Step:
//2.0 Attach it. Yes I know it sets it as unchanged. But let me do the magic trick!!!
dbIboID.OrderProcess = Order.ToList(); //CHANGED
dbs.OrderDB.Attach(dbIboID);
//2.1 Extract original values from the database.
var originalProducts = dbs.OrderProcessDB.Where(x => x.OrderProcessID == Order[0].OrderProcessID).ToList();
var userProducts = Order.ToList();
//This is a dictionary which will be used to set all other entities with their correct states!
Dictionary<int, System.Data.Entity.EntityState> StateProduct = new Dictionary<int, System.Data.Entity.EntityState>();
//2.3 Find new added products. addedProducts = userProducts[key] - originalProducts[key]
if(userProducts.Count > originalProducts.Count)
{
for (int i = originalProducts.Count - 1; i < userProducts.Count; i++ )
{
StateProduct.Add(i, System.Data.Entity.EntityState.Added);
}
}
//2.3 Find Deleted products = originalProducts - userProducts. Do reverse of the addedProducts
else
{
for (int i = userProducts.Count - 1; i < originalProducts.Count; i++)
{
StateProduct.Add(i, System.Data.Entity.EntityState.Deleted);
}
}
//2.4 Find modified products modifiedProducts = [userProducts - addedProducts] different originalProducts
//This is not 100% fool proof. Because there will be times that I will always have a modification,
// when objects remained unchanged.
for (int s = 0; s < userProducts.Count; s++ )
{
StateProduct.Add(s, System.Data.Entity.EntityState.Modified);
}
//2.5 Painting Process:
for (int i = 0; i < dbIboID.OrderProcess.Count(); i++ )
{
dbs.DB.Entry(dbIboID.OrderProcess[i]).State = StateProduct[i];
}
The code as you have shown it should not produce that exception, because the dictionary was allocated immediately prior to the loop, and thus should be empty, and the items being added all are unique integers.
My guess is that the dictionary already had some values in it. If so, then using Add to set a value will throw an ArgumentException, since the value corresponding to that key can only be replaced, not added, for the Dictionary class only allows one value per key.
So, if you expect the dictionary not to already have a value for a key, and want an error exception to be thrown if it does, do:
StateProduct.Add(s, EntityState.Modified)
If you want to add or replace a value, do:
StateProduct[s] = EntityState.Modified;

Categories