How to delete an item from a generic list - c#

I have a generic list
How do I remove an item?
EX:
Class Student
{
private number;
public Number
{
get( return number;)
set( number = value;)
}
private name;
public Name
{
get( return name;)
set( name = value;)
}
main()
{
static List<student> = new list<student>();
list.remove...???
}
}

Well, there is nothing to remove because your list is empty (you also didn't give it an identifier, so your code won't compile). You can use the Remove(T item) or RemoveAt(int index) to remove an object or the object at a specified index respectively (once it actually contains something).
Contrived code sample:
void Main(...)
{
var list = new List<Student>();
Student s = new Student(...);
list.Add(s);
list.Remove(s); //removes 's' if it is in the list based on the result of the .Equals method
list.RemoveAt(0); //removes the item at index 0, use the first example if possible/appropriate
}

From your comments I conclude that you read student name from input and you need to remove student with given name.
class Student {
public string Name { get; set; }
public int Number { get; set; }
public Student (string name, int number)
{
Name = name;
Number = number;
}
}
var students = new List<Student> {
new Student ("Daniel", 10),
new Student ("Mike", 20),
new Student ("Ashley", 42)
};
var nameToRemove = Console.ReadLine ();
students.RemoveAll (s => s.Name == nameToRemove); // remove by condition
Note that this will remove all students with given name.
If you need to remove the first student found by name, first use First method to find him, and then call Remove for the instance:
var firstMatch = students.First (s => s.Name == nameToRemove);
students.Remove (firstMatch);
If you want to ensure there is only one student with given name before removing him, use Single in a similar fashion:
var onlyMatch = students.Single (s => s.Name == nameToRemove);
students.Remove (onlyMatch);
Note that Single call fails if there is not exactly one item matching the predicate.

List<Student> students = new List<Student>();
students.Add(new Student {StudentId = 1, StudentName = "Bob",});
students.RemoveAt(0); //Removes the 1st element, will crash if there are no entries
OR to remove a known Student.
//Find a Single Student in the List.
Student s = students.Where(s => s.StudentId == myStudentId).Single();
//Remove that student from the list.
students.Remove(s);

Well, you didn't give your list a name, and some of your syntax is wonky.
void main()
{
static List<Student> studentList = new List<Student>();
}
// later
void deleteFromStudents(Student studentToDelete)
{
studentList.Remove(studentToDelete);
}
There are more remove functions detailed here: C# List Remove Methods

int count=queue.Count;
while(count>0)
{
HttpQueueItem item = queue[0];
/// If post succeeded..
if (snd.IsNotExceedsAcceptedLeadsPerDayLimit(item.DataSaleID, item.AcceptedLeadsPerDayLimit) && snd.PostRecord(item.DataSaleDetailID, item.PostString, item.duplicateCheckHours, item.Username, item.Password, item.successRegex))
{
if (item.WaitTime > 0)
Thread.Sleep(item.WaitTime);
queue.Remove(item);
}
///If Exceeds Accepted leads per day limit by DataSale..
else if (!snd.IsNotExceedsAcceptedLeadsPerDayLimit(item.DataSaleID, item.AcceptedLeadsPerDayLimit))
{
queue.RemoveAll(obj => obj.DataSaleID == item.DataSaleID);
}
/// If Post failed..
else //if (!snd.PostRecord(item.DataSaleDetailID, item.PostString, item.duplicateCheckHours, item.Username, item.Password, item.successRegex))
{
queue.Remove(item);
}
count = queue.Count;
}

To delete a row or record from generic list in grid view, just write this code-
List<Address> people = new List<Address>();
Address t = new Address();
people.RemoveAt(e.RowIndex);
grdShow.EditIndex = -1;
grdShow.DataSource = people;
grdShow.DataBind();

Maybe you can use a Dictionary<string, Student> instead of the List<Student>.
When you add a Student, add its ID or Name or whatever can uniquely identify it. Then you can simply call myStudents.Remove(myStudentId)

Try linq:
var _resultList = list.Where(a=>a.Name != nameToRemove).Select(a=>a);

I made a program that contains 7 cards, then shuffle and I hope to take in order to help them
class Program
{
static void Main(string[] args)
{
Random random = new Random();
var cards = new List<string>();
//CARDS VECRTOR
String[] listas = new String[] { "Card 1", "Card 2", "Card 3", "Card 4", "Card 5", "Card 6", "Card 7"};
for (int i = 0; i<= cards.Count; i++)
{
int number = random.Next(0, 7); //Random number 0--->7
for (int j = 0; j <=6; j++)
{
if (cards.Contains(listas[number])) // NO REPEAT SHUFFLE
{
number = random.Next(0, 7); //AGAIN RANDOM
}
else
{
cards.Add(listas[number]); //ADD CARD
}
}
}
Console.WriteLine(" LIST CARDS");
foreach (var card in cards)
{
Console.Write(card + " ,");
}
Console.WriteLine("Total Cards: "+cards.Count);
//REMOVE
for (int k = 0; k <=6; k++)
{
// salmons.RemoveAt(k);
Console.WriteLine("I take the card: "+cards.ElementAt(k));
cards.RemoveAt(k); //REMOVE CARD
cards.Insert(k,"Card Taken"); //REPLACE INDEX
foreach (var card in cards)
{
Console.Write(card + " " + "\n");
}
}
Console.Read(); //just pause
}
}

Related

How to loop to add items up to a quantity

I'm trying to make a loop to add 10 items but only add one with the number 10.
List<Contact> listContact;
for (int cuantidade = 0; cuantidade < 10; cuantidade++)
{
listContact = new List<Contact>(cuantidade)
{
new Contact()
{
Name = cuantidade.ToString(),
Number = cuantidade.ToString(),
},
};
}
this.listBoxNames.ItemsSource = listContact;
What am I doing wrong?
Try this:
var contactList= new List<Contact>();
for (int cuantidade = 0; cuantidade < 10; cuantidade++)
{
contactList.Add(new Contact
{
Name = cuantidade.ToString(),
Number = cuantidade.ToString(),
});
}
this.listBoxNames.ItemsSource = contactList;
You need to set the list before the loop. With your current code, at every iteration the list is redefined and resets...
Here is an alternate example pair using Linq
The first just gets 10
The second starts at one point (13) and then gets the next 7
I used a number generator just for the example but it could be any source.
using System;
using System.Linq;
using System.Collections.Generic;
public class Program
{
public static void Main()
{
// Generate a sequence of integers from 9 to 50
IEnumerable<int> quanityNumbers = Enumerable.Range(9, 50);
// just take the first 10:
List<Contact> contacts = quanityNumbers
.Take(10)
.Select(a => new Contact()
{
Name = a.ToString(),
Number = a.ToString()
}).ToList();
Console.WriteLine($"Hello World contacts has {contacts.Count} items");
foreach (var c in contacts)
{
Console.WriteLine($"contacts has Name: {c.Name} with Number: {c.Number}");
}
//Start at some point and take 7 from there:
List<Contact> contactsFromTo = quanityNumbers
.Skip(13)
.Take(7)
.Select(a => new Contact()
{
Name = a.ToString(),
Number = a.ToString()
}).ToList();
Console.WriteLine($"Hello World contactsFromTo has {contactsFromTo.Count} items");
foreach (var c in contactsFromTo)
{
Console.WriteLine($"contactsFromTo has Name: {c.Name} with Number: {c.Number}");
}
}
public class Contact
{
public string Name { get; set; }
public string Number { get; set; }
}
}

Extract overlapping substrings from a list of strings using LINQ

I have the following list of strings {"a","b","c","d","e"}. How can I obtain sublists of length 3 using LINQ like this:
{"a","b","c"}
{"b","c","d"}
{"c","d","e"}
I am not looking for every combination
var list = students.OrderBy(student => student.LastName)
.Select(student => student);
List<Student> sortedStudents = list.ToList();
var triplets = from x in sortedStudents
from y in sortedStudents
from z in sortedStudents
select new { x, y, z};
StudentListBox.ItemsSource = triplets;
I am not looking for something like
{"a","b","c"}
{"a","b","d"}
{"a","b","e"}
.............
{"d","a","b"}
{"d","a","c"}
{"d","a","e"} and so on
Student class
class Student
{
public Student()
{
}
public String FirstName
{
get;
set;
}
public String LastName
{
get;
set;
}
public DateTime Birthday
{
get;
set;
}
public override string ToString()
{
return FirstName + " " + LastName;
}
}
You can us an overload of Select which gets the index of current element as an extra parameter to the selector and use it like this:
var triplets = sortedStudents.Take(list.Count - 2)
.Select((x, i) => new { S1 = x, S2 = list[i+1], S3 = list[i+2] });
Here is one approach with Linq - .Take(3)defines length of 3
string[] input = { "a", "b", "c", "d", "e" };
var result = Enumerable.Range(0, input.Length - 2).Select(x => input.Skip(x).Take(3));
Just loop the strings in your array:
public IEnumerable<IEnumerable<string>> GetTriples(string[] myArray)
{
for (int i = 0; i < myArray.Length - 2; i++)
{
yield return myArray.Skip(i).Take(3);
}
}
This codes loops every string in your array and gets the next two strings.
Assuming (because you haven't got a complete code sample) that you want to take triples of items from your collection in the order in which they appear, you can use a combination of Skip and Take to give you subsets representing your triples.
var triplets = new List<IEnumerable<Student>>();
for(int i = 0; i < (sortedStudents.Count - 2); i++)
{
triplets.Add(sortedStudents.Skip(i).Take(3));
}

Pick Random string from List<string> with exclusions and non-repetitive pick

im trying to write a program that would let a user:
Load a set of string.
Loop through the set, and pick another string from the same set.
Avoid a picked string from being picked again.
Have specific strings not be able to pick specified strings.
Example is table below:
And below table is a sample scenario:
How am i supposed to do this the easy way?
i have below code, but it is taking like forever to generate a valid set since it restarts everything if there are nothing left to pick, while not eliminating the possibility.
private List<Participant> _participants;
AllOverAgain:
var pickedParticipants = new List<Participant>();
var participantPicks = new List<ParticipantPick>();
foreach(var participant in _participants)
{
var pickedParticipantNames = from rp in participantPicks select rp.PickedParticipant;
var picks = (from p in _participants where p.Name != participant.Name & !Utilities.IsInList(p.Name, pickedParticipantNames) select p).ToList();
var pick = picks[new Random().Next(0, picks.Count())];
if(pick == null)
{
UpdateStatus($"No Available Picks left for {participant.Name}, Restarting...");
goto AllOverAgain;
}
var exclusions = participant.Exclusions.Split(',').Select(p => p.Trim()).ToList();
if(exclusions.Contains(pick.Name))
{
UpdateStatus($"No Available Picks left for {participant.Name}, Restarting...");
goto AllOverAgain;
}
participantPicks.Add(new ParticipantPick(participant.Name, pick.Name, participant.Number));
}
return participantPicks; // Returns the final output result
The Participant Class consists of these Properties:
public string Name { get; set; }
public string Number { get; set; }
public string Exclusions { get; set; }
The ParticipantPick Class consists of these Properties:
public string Participant { get; set; }
public string PickedParticipant { get; set; }
public string Number { get; set; }
One way you can solve this is by using a dictionary, using a composite key of a tuple and the matching value of a datatype bool.
Dictionary<Tuple<string, string>, bool>
The composite key Tuple<sring,string> will contain every permutation of participants and match them to their appropriate bool value.
For example, the dictionary filled with values such as:
Dictionary<Tuple<"Judith","James">, true>
...would be indicating that Judith picking James is valid.
So lets create a dictionary with every single possible combination of participants, and set the value of them to true for them being valid at the start of the program.
This can be accomplished by a cartesian join using an array with itself.
Dictionary<Tuple<string, string>, bool> dictionary = participants.SelectMany(left => participants, (left, right) => new Tuple<string, string>(left, right)).ToDictionary(item=> item, item=>true);
After getting every permutation of possible picks and setting them to true, we can go through the "not allowed to pick" lists and change the dictionary value for that composite key to false.
dictionary[new Tuple<string, string>(personNotAllowing, notAllowedPerson)] = false;
You can remove a participant from picking itself by using a loop in the following way:
for(int abc=0;abc<participants.Length;abc++)
{
//remove clone set
Tuple<string, string> clonePair = Tuple.Create(participants[abc], participants[abc]);
dictionary.Remove(clonePair);
}
Or by simply changing the value of the clone pair to false.
for(int abc=0;abc<participants.Length;abc++)
{
dictionary[Tuple.Create(participants[abc],participants[abc])] = false;
}
In this example program, I create a string[] of participants, and a string[] for the respective list of people they do not allow. I then perform a cartesian join, the participants array with itself. This leads to every permutation, with an initial true boolean value.
I change the dictionary where the participants are not allowed to false, and display the example dictionary.
Afterward, I create 10 instances of random participants who are picking other random participants and test if it would be valid.
Every time a participant picks another participant, I check that composite key to see if it has a value of true.
If it does result in a valid pick, then every combination of the resulting participant who was picked gets set to false.
for(int j=0; j<participants.Length;j++)
{
//Make the partner never be able to be picked again
Tuple<string, string> currentPair2 = Tuple.Create(partner, participants[j]);
try
{
dictionary[currentPair2] = false;
}
catch
{
}
}
This concept is better illustrated with running the code.
The demo:
static void Main(string[] args)
{
//Create participants set
string[] participants = {"James","John","Tyrone","Rebecca","Tiffany","Judith"};
//Create not allowed lists
string[] jamesNotAllowedList = {"Tiffany", "Tyrone"};
string[] johnNotAllowedList = {};
string[] tyroneNotAllowedList = {};
string[] rebeccaNotAllowedList ={"James", "Tiffany"};
string[] judithNotAllowedList = {};
//Create list of not allowed lists
string[][] notAllowedLists = { jamesNotAllowedList, johnNotAllowedList, tyroneNotAllowedList, rebeccaNotAllowedList, judithNotAllowedList};
//Create dictionary<Tuple<string,string>, bool> from participants array by using cartesian join on itself
Dictionary<Tuple<string, string>, bool> dictionary = participants.SelectMany(left => participants, (left, right) => new Tuple<string, string>(left, right)).ToDictionary(item=> item, item=>true);
//Loop through each person who owns a notAllowedList
for (int list = 0; list < notAllowedLists.Length; list++)
{
//Loop through each name on the not allowed list
for (int person = 0; person<notAllowedLists[list].Length; person++)
{
string personNotAllowing = participants[list];
string notAllowedPerson = notAllowedLists[list][person];
//Change the boolean value matched to the composite key
dictionary[new Tuple<string, string>(personNotAllowing, notAllowedPerson)] = false;
Console.WriteLine(personNotAllowing + " did not allow " + notAllowedPerson);
}
}
//Then since a participant cant pick itself
for(int abc=0;abc<participants.Length;abc++)
{
//remove clone set
Tuple<string, string> clonePair = Tuple.Create(participants[abc], participants[abc]);
dictionary.Remove(clonePair);
}
//Display whats going on with this Dictionary<Tuple<string,string>, bool>
Console.WriteLine("--------Allowed?--Dictionary------------\n");
Console.WriteLine(string.Join(" \n", dictionary));
Console.WriteLine("----------------------------------------\n\n");
//Create Random Object
Random rand = new Random();
//Now that the data is organized in a dictionary..
//..Let's have random participants pick random participants
//For this demonstration lets try it 10 times
for (int i=0;i<20;i++)
{
//Create a new random participant
int rNum = rand.Next(participants.Length);
string randomParticipant = participants[rNum];
//Random participant picks a random participant
string partner = participants[rand.Next(participants.Length)];
//Create composite key for the current pair
Tuple<string, string> currentPair = Tuple.Create(partner,randomParticipant);
//Check if it's a valid choice
try
{
if (dictionary[currentPair])
{
Console.WriteLine(randomParticipant + " tries to pick " + partner);
Console.WriteLine("Valid.\n");
//add to dictionary
for(int j=0; j<participants.Length;j++)
{
//Make the partner never be able to be picked again
Tuple<string, string> currentPair2 = Tuple.Create(partner, participants[j]);
try
{
dictionary[currentPair2] = false;
}
catch
{
}
}
}
else
{
Console.WriteLine(randomParticipant + " tries to pick " + partner);
Console.WriteLine(">>>>>>>>Invalid.\n");
}
}
catch
{
//otherwise exception happens because the random participant
//And its partner participant are the same person
//You can also handle the random participant picking itself differently
//In this catch block
//Make sure the loop continues as many times as necessary
//by acting like this instance never existed
i = i - 1;
}
}
Console.ReadLine();
}
This code will always give you output that adheres to your criteria:
public static class Program
{
public static void Main(string[] args)
{
var gathering = new Gathering();
gathering.MakeSelections();
foreach (var item in gathering.participants)
{
Console.WriteLine(item.name + ":" + item.selectedParticipant);
}
}
public class Participant
{
public string name;
public List<string> exclusions;
public string selectedParticipant;
}
public class Gathering
{
public List<Participant> participants;
public List<string> availableParticipants;
public List<string> usedNames;
public Dictionary<string, string> result;
public Gathering()
{
//initialize participants
participants = new List<Participant>();
participants.Add(new Participant
{
name = "James",
exclusions = new List<string> { "Tiffany", "Tyrone" }
});
participants.Add(new Participant
{
name = "John",
exclusions = new List<string> { }
});
participants.Add(new Participant
{
name = "Judith",
exclusions = new List<string> { }
});
participants.Add(new Participant
{
name = "Rebecca",
exclusions = new List<string> { "James", "Tiffany" }
});
participants.Add(new Participant
{
name = "Tiffany",
exclusions = new List<string> { }
});
participants.Add(new Participant
{
name = "Tyrone",
exclusions = new List<string> { }
});
//prevent participants from selecting themselves
foreach (Participant p in participants)
{
p.exclusions.Add(p.name);
}
//create list of all the names (all available participants at the beginning)
availableParticipants = participants.Select(x => x.name).ToList();
}
public void MakeSelections()
{
Participant currentParticipant;
Random randy = new Random();
//Sort Participants by the length of their exclusion lists, in descending order.
participants.Sort((p1, p2) => p2.exclusions.Count.CompareTo(p1.exclusions.Count));
//Get the first participant in the list which hasn't selected someone yet
currentParticipant = participants.FirstOrDefault(p => p.selectedParticipant == null);
while (currentParticipant != null)
{
//of the available participants, create a list to choose from for the current participant
List<string> listToChooseFrom = availableParticipants.Where(x => !currentParticipant.exclusions.Contains(x)).ToList();
//select a random participant from the list of eligible ones to be matched with the current participant
string assignee = listToChooseFrom[randy.Next(listToChooseFrom.Count)];
currentParticipant.selectedParticipant = assignee;
//remove the selected participant from the list of available participants
availableParticipants.RemoveAt(availableParticipants.IndexOf(assignee));
//remove the selected participant from everyone's exclusion lists
foreach (Participant p in participants)
if (p.exclusions.Contains(assignee))
p.exclusions.RemoveAt(p.exclusions.IndexOf(assignee));
//Resort Participants by the length of their exclusion lists, in descending order.
participants.Sort((p1, p2) => p2.exclusions.Count.CompareTo(p1.exclusions.Count));
//Get the first participant in the list which hasn't selected someone yet
currentParticipant = participants.FirstOrDefault(p => p.selectedParticipant == null);
}
//finally, sort by alphabetical order
participants.Sort((p1, p2) => p1.name.CompareTo(p2.name));
}
}
}
In the simpler version, the items can just be shuffled:
string[] source = { "A", "B", "C", "D", "E", "F" };
string[] picked = source.ToArray(); // copy
var rand = new Random();
for (int i = source.Length - 1, r; i > 0; --i)
{
var pick = picked[r = rand.Next(i)]; // pick random item less than the current one
picked[r] = picked[i]; // and swap with the current one
picked[i] = pick;
Console.WriteLine(i + " swapped with " + r);
}
Console.WriteLine("\nsource: " + string.Join(", ", source) +
"\npicked: " + string.Join(", ", picked));
sample result:
5 swapped with 4
4 swapped with 2
3 swapped with 0
2 swapped with 1
1 swapped with 0
source: A, B, C, D, E, F
picked: F, D, B, A, C, E
or, the source can be optionally shuffled, and each person can pick the person that is next in the list.

Why is the item that exists in the CheckedListBox not found via IndexOf()?

I have this code:
if (currentWeekSaved)
{
DateTime currentWeek = Convert.ToDateTime(comboBoxWeekToSchedule.SelectedValue);
AssignmentHistory ah = AYttFMConstsAndUtils.AssignmentHistList
.FirstOrDefault(i => i.WeekOfAssignment == currentWeek && i.TalkType == BIBLE_READING_TALK_TYPE);
if (ah != null)
{
var assignedStudentFirstname = AYttFMConstsAndUtils.GetStudentFirstNameForID(ah.StudentID_FK);
var assignedStudentLastname = AYttFMConstsAndUtils.GetStudentLastNameForID(ah.StudentID_FK);
assignedStudent = new Student() {FirstName = assignedStudentFirstname, LastName = assignedStudentLastname, StudentID = ah.StudentID_FK};
}
}
List<Student> BRStudents =
AYttFMConstsAndUtils.StudentsList.Where(h => h.EnrolledInAYttFM)
.Where(i => i.RecommendedNextTalkTypeID.Equals(BIBLE_READING_TALK_TYPE))
.OrderBy(j => j.WeekOfLastAssignment)
.ToList();
if (null != assignedStudent)
{
// If exists in list, remove it first, and then add it back at the top
//int assignedStudentIndex = BRStudents.IndexOf(assignedStudent);
int assignedStudentIndex = checkedListBoxBR.Items.IndexOf(assignedStudent.FullName);
if (assignedStudentIndex > -1)
{
BRStudents.RemoveAt(assignedStudentIndex);
}
BRStudents.Insert(0, assignedStudent);
}
checkedListBoxBR.DataSource = BRStudents;
checkedListBoxBR.DisplayMember = "FullName";
checkedListBoxBR.ValueMember = "StudentID";
If there is already someone assigned for the week being processed, I want to first remove them from checkedListBoxBR and then add them back at index 0. However, even when the person is in checkedListBoxBR, this line:
int assignedStudentIndex =
checkedListBoxBR.Items.IndexOf(assignedStudent.FullName);
...fails to find them. The value of "assignedStudent.FullName" does equal the value of one of the items; as seen above, "FullName" is the ValueMember for CheckedListBox:
On stepping through it, the list of students, BRStudents, has 2 members, the person already assigned and another person; "assignedStudent" is the person already assigned; checkedListBoxBR has three items, the person already assigned plus two others.
So why is assignedStudentIndex -1 when the person assigned is represented in FullName? It's true that I don't explicitly assign FullName in this line:
assignedStudent = new Student() {FirstName = assignedStudentFirstname, LastName = assignedStudentLastname, StudentID = ah.StudentID_FK};
...but FullName is a calculated field in the class:
public class Student
{
public int StudentID { get; set; }
. . .
public string FirstName { get; set; }
public string LastName { get; set; }
. . .
public string FullName
{
get
{
return $"{FirstName} {LastName}";
}
set { }
}
}
So why in tarnation is "So and So" not found in the CheckedListBox's items when it is most decidedly there?
UPDATE
Olivier's suggestion seems good ("iterate through checkedListBoxBR.Items and see if you find a match between the item's DisplayMember and the assignedStudent.FullName"). But how? I thought maybe something like this would do it:
for (int i = 0; i < checkedListBoxBR.Items.Count; i++)
{
if checkedListBoxBR.Items[0].DisplayMember.Equals(assignedStudent.FullName)
{
checkedListBoxBR.RemoveAt(i);
}
}
...but "DisplayMember" is not recognized here (nor is "RemoveAt").
UPDATE 2
Responding to Olivier's nudgings, I fixed the above to be:
for (int i = 0; i < checkedListBoxBR.Items.Count; i++)
{
if checkedListBoxBR.Items[i].DisplayMember.Equals(assignedStudent.FullName)
{
checkedListBoxBR.Items.RemoveAt(i);
}
}
...but it still considers DisplayMember to be property-non-grata.
UPDATE 3
I have simplified the code, and it's working pretty well. Here is the simplified version:
// Called whenever the week changes (a new week is navigated to/selected in the combobox)
private void PopulateBibleReadingComboBox()
{
int BIBLE_READING_TALK_TYPE = 1;
Student assignedStudent = null;
List<Student> assignedStudents = null;
// If the week has been saved, get the student who has been assigned the Bible Reading
if (currentWeekSaved)
{
DateTime currentWeek = Convert.ToDateTime(comboBoxWeekToSchedule.SelectedValue);
AssignmentHistory ah = AYttFMConstsAndUtils.AssignmentHistList
.FirstOrDefault(i => i.WeekOfAssignment == currentWeek && i.TalkType == BIBLE_READING_TALK_TYPE);
if (ah != null)
{
var assignedStudentFirstname = AYttFMConstsAndUtils.GetStudentFirstNameForID(ah.StudentID_FK);
var assignedStudentLastname = AYttFMConstsAndUtils.GetStudentLastNameForID(ah.StudentID_FK);
assignedStudent = new Student() {FirstName = assignedStudentFirstname, LastName = assignedStudentLastname, StudentID = ah.StudentID_FK};
// Use the ID to get the student and put him/her in a 1-person list (needed for
// the subsequent LINQ Union)
assignedStudents =
AYttFMConstsAndUtils.StudentsList.Where(i => i.StudentID == ah.StudentID_FK).ToList();
}
}
// Get all the candidates for assignment
List<Student> BRStudents =
AYttFMConstsAndUtils.StudentsList.Where(h => h.EnrolledInAYttFM)
.Where(i => i.RecommendedNextTalkTypeID.Equals(BIBLE_READING_TALK_TYPE))
.OrderBy(j => j.WeekOfLastAssignment)
.ToList();
if (null != assignedStudent)
{
List<Student> allBRStudents = assignedStudents.Union(BRStudents).ToList();
checkedListBoxBR.DataSource = allBRStudents;
checkedListBoxBR.DisplayMember = "FullName";
checkedListBoxBR.ValueMember = "StudentID";
}
else // No assigned student found, bind to the candidate students only
{
checkedListBoxBR.DataSource = BRStudents;
checkedListBoxBR.DisplayMember = "FullName";
checkedListBoxBR.ValueMember = "StudentID";
}
// In either case, highlight and check the first one now
checkedListBoxBR.SelectedIndex = 0;
checkedListBoxBR.SetItemChecked(0, true);
}
I can see two things wrong.
First, you populate checkedListBoxBR after you check for the presence of a certain item.
Secondly, you are comparing apples and oranges. checkedListBoxBR.Items is a Collection of objects, and you are comparing that to a string (assignedStudent.FullName) via indexOf. That will not work.
A better solution would be to iterate through checkedListBoxBR.Items and see if you find a match between the item's DisplayMember and the assignedStudent.FullName.
Or you could use a Student object in the the indexOf call, but then you need to make sure you implement IEquatable, override Equals, GetHashCode, etc.
The items of your checkedListBoxBR are of type Student, because the items in your DataSource are of type Student:
List<Student> BRStudents = [...]
checkedListBoxBR.DataSource = BRStudents;
By using the IndexOf function with a string (Student.FullName) as a parameter, you are comparing many Student objects to one string. No Student is equal to your string so you get the result of -1. Try modifing your code like this:
int assignedStudentIndex = checkedListBoxBR.Items.IndexOf(assignedStudent);
Additionally you might want to override the Equals method.
Edit:
As #olivier-de-meulder correctly pointed out you need to move these lines above your lookup to make any option work:
checkedListBoxBR.DataSource = BRStudents;
checkedListBoxBR.DisplayMember = "FullName";
checkedListBoxBR.ValueMember = "StudentID";

Linq write new list from old list sublist, change said list, write back to old list

I'm rather new to Linq. I'm having trouble coding this.
I have a list with many different sublists.
oldList[0] some type
oldList[1] another different type
oldList[2] the type I want
oldList[3] more types
I want to select all the parameters from a specific type and write them to a temp list.
If that temp list is empty, I want to assign some values (values don't actually matter).
After changing the values, I want to write temp list back into oldList.
Please advise. This is a huge learning experience for me.
public void myFunction(list)
{
//list contains at least 5 sublists of various type
//check if the type I want is null
IEnumerable<TypeIWant> possiblyEmptyList = list.OfType<TypeIWant>(); //find the type I want from the list and save it
if (possiblyEmptyList == null) //this doesn't work and possiblyEmptyList.Count <= 1 doesn't work
{
//convert residence address to forwarding address
IEnumerable<ReplacementType> replacementList = list.OfType<ReplacementType>();
forwardingAddress = replacementList.Select(x => new TypeIWant /* this statement functions exactly the way I want it to */
{
Address1 = x.Address1,
Address2 = x.Address2,
AddressType = x.AddressType,
City = x.City,
CountryId = x.CountryId,
CountyRegion = x.CountyRegion,
Email = x.Email,
ConfirmEmail = x.ConfirmEmail,
Fax = x.Fax,
Telephone = x.Telephone,
State = x.State,
PostalCode = x.PostalCode
});
//write forwarding address back to list
//don't know how to do this
}
LINQ purpose is querying. It doesn't allow you to replace some items in collection with other items. Use simple loop instead:
IEnumerable<TypeIWant> possiblyEmptyList = list.OfType<TypeIWant>();
if (!possiblyEmptyList.Any())
{
for (int i = 0; i < list.Count; i++)
{
ReplacementType item = list[i] as ReplacementType;
if (item == null)
continue;
list[i] = ConvertToTypeIWant(item);
}
}
And conversion (which is better to do with something like automapper):
private TypeIWant ConvertToTypeIWant(ReplacementType x)
{
return new TypeIWant
{
Address1 = x.Address1,
Address2 = x.Address2,
AddressType = x.AddressType,
City = x.City,
CountryId = x.CountryId,
CountyRegion = x.CountyRegion,
Email = x.Email,
ConfirmEmail = x.ConfirmEmail,
Fax = x.Fax,
Telephone = x.Telephone,
State = x.State,
PostalCode = x.PostalCode
};
}
Not LINQ but an example.
class Program
{
static void Main(string[] args)
{
// Vars
var list = new List<List<string>>();
var a = new List<string>();
var b = new List<string>();
var c = new List<string> { "one", "two", "three" };
var d = new List<string>();
// Add Lists
list.Add(a);
list.Add(b);
list.Add(c);
list.Add(d);
// Loop through list
foreach (var x in list)
{
if (x.Count < 1)
{
var tempList = new List<string>();
tempList.Add("some value");
x.Clear();
x.AddRange(tempList);
}
}
// Print
int count = 0;
foreach (var l in list)
{
count++;
Console.Write("(List " + count + ") ");
foreach (var s in l)
{
Console.Write(s + " ");
}
Console.WriteLine("");
}
}
}
(List 1) some value
(List 2) some value
(List 3) one two three
(List 4) some value

Categories