custom sorting in a bindinglist of keyvaluepairs - c#

I have a bindinglist of keyvaluepair filled dynamicaly.
BindingList<KeyValuePair<int, string>> Homelist = new BindingList<KeyValuePair<int, string>>();
foreach (ListItem item in listBox2.Items)
{
Homelist.Add(new KeyValuePair<int, string>(item.Id, item.Name));
}
The list has key(id) and value(text) as shown
I want to sort the first 5 items asc and then the rest items also asc.the sorting must be by value and not by key.
example: if I have the values : 4,5,8,7,6,10,9,3,2,1,22 the sorting result must be 4,5,6,7,8 ,1,2,3,9,10,22.Any idea?
solved answer:
public int Compare(KeyValuePair<int,string> a, KeyValuePair<int,string> b)
{
return a.Value.CompareTo(b.Value);
}
List<keyvaluepair><int,>> Playinglist = new List<keyvaluepair><int,>>();
for (int i = 0; i < 5; i ++)
{
Playinglist.Add(Homelist[i]);
}
Playinglist.Sort(Compare);
List<keyvaluepair><int,>> Benchlist = new List<keyvaluepair><int,>>();
for (int i = 5; i < Homelist.Count(); i++)
{
Benchlist.Add(Homelist[i]);
}
Benchlist.Sort(Compare);
//union 2 lists
var unionedList = new List<keyvaluepair><int,>>();
unionedList.AddRange(Playinglist.Union(Benchlist));
Homelist.Clear();
for (int i = 0; i < unionedList.Count(); i++)
{
Homelist.Insert(i, unionedList[i]);
}
game.GetHomelist = Homelist;

The idea that Tony Hopkinson said is to chop the list into two. Sort them separately and then join them back togther.After that clear the bindlist and filled from the join list. Sorting can be applied only in List<> and not to the BindLists<>.The answere is in edited question

Related

how to create a loop that creates lists

I want to create a loop that makes lists the name of the lists that need to come from another list.
I tried doing it like that.
for (int i = 0; i < Names.Count; i++)
{
List<string> Name[i] = new List<string>();
}
Just pass the source collection in the list constructor, like this
var newList = new List<string>(Names);
If you want more control, you can still do your loop, but declare the destination list first:
var newList = new List<string>();
for (int i = 0; i < Names.Count; i++)
{
newList.Add(Names[i]);
}
And finally, if you need a list of lists, where each list is named, you'd use a different data structure, for example a Dictionary<string, List<string>> instead:
var listOfLists = new Dictionary<string, List<string>>();
for (int i = 0; i < Names.Count; i++)
{
listOfLists.Add(
Names[i], // <--- the name of the list is the key
new() // <--- the named list (initially empty)
);
}
Which, in modern C#, can be shortened further to become
var listOfLists = Names.ToDictionary(name => name, _ => new List<string>());

Change Key for a SortedList

I need a Sorted list, but after I remove an item from the list I then need to adjust the keys of the other items before adding new items to the list.
You are not allowed to change the key for the items in a "SortedList".
What tool would be best for doing this.
Example code
timedEvQue.Add(3, "First");
timedEvQue.Add(7, "Second");
timedEvQue.Add(9, "Third");
int decAmnt = (int)timedEvQue.Keys[0];
timedEvQue.RemoveAt(0);
for (int i = 0; i < timedEvQue.Count; ++i)
{
timedEvQue.Keys[i] = timedEvQue.Keys[i] - decAmnt; //runtime error here
}
timedEvQue.Add(5, "Forth");
There isn't typically a change key operation for dictionary/hash map type data structures as they would essentially just remove and add the item again. So just remove and add the item back.
timedEvQue.Add(3, "First");
timedEvQue.Add(7, "Second");
timedEvQue.Add(9, "Third");
int decAmnt = (int)timedEvQue.Keys[0];
timedEvQue.RemoveAt(0);
for (int i = 0; i < timedEvQue.Count; ++i)
{
int oldKey = timedEvQue.Keys[i];
string val = timedEvQue[oldKey];
int newKey = oldKey - decAmnt;
timedEvQue.Remove(oldKey);
timedEvQue.Add(newKey, val);
}
timedEvQue.Add(5, "Forth");

Using sortedList to count words in a List

For my homework, I have to use a SortedList to count words in a List with SortedList taking each entry and sorting it in alphabetical order before inserting. When it comes to display the data to the user, the data displayed should be displayed with sorting according to value instead of key.
Below is my attempt at this but I am getting 3 errors and I don't know how to resolve it. I am not allowed to use LINQ for this.
List<string> words = new List<string>(); <--- Already populated
This is my code of this implementation and I get 3 errors:
SortedList<string, int> d = new SortedList<string, int>();
bool InsideOfList = false;
foreach (string word in words)
{
InsideOfList = false;
foreach (KeyValuePair<string, int> keyvalPair in d)
{
if (keyvalPair.Key == word)
{
keyvalPair.Value += 1;
InsideOfList = true;
}
}
if (InsideOfList == false)
{
d.Add(word,1);
}
}
//Now instead of sorting by key I want to sort by value instead
SortedList<int, string> tempSortList = new SortedList<int, string>();
foreach (KeyValuePair<string, int> keyvalPair in d)
{
//trying to swap the value of previous SortedList with the Key of the new SortedList
tempSortList.Add(keyvalPair.Value, keyvalPair.Key);
}
for (int i = 0; i < 20; i++)
{
Console.WriteLine("\t{0}:\t{1}", tempSortList.GetKey(i), tempSortList.GetByIndex(i));
}
Here are my errors:
Property or indexer 'System.Collections.Generic.KeyValuePair<string,int>.Value' cannot be assigned to -- it is read only
'System.Collections.Generic.SortedList<int,string>' does not contain a definition for 'GetKey'
'System.Collections.Generic.SortedList<int,string>' does not contain a definition for 'GetByIndex'
You are confusing two things here. One is SortedList() and other is SortedList().
GetKey and GetKeyList are not present in SortedList(). You can use this instead of GetKey
tempSortList.ElementAt(index); // This will return you a KeyValuePair.
And for the first error you cannot assign value keyvalPair.Value has only getter. So you cannot set its value by doing += 1.
This is not quite good. Needs some improvement but it will work.
for (int i = 0; i < d.Count; i++)
{
if (d.ElementAt(i).Key == word)
{
d.Values[i] += 1;
}
}
or
for (int i = 0; i < d.Count; i++)
{
if (d.ElementAt(i).Key == word)
{
var val = d.ElementAt(i).Value + 1;
d.RemoveAt(i);
d.Add(word, val);
}
}
Please modify this line and check if it works. it should.
Console.WriteLine("\t{0}:\t{1}", tempSortList.GetKey(i), tempSortList.GetByIndex(i));
to
var key = tempSortedList.Keys[i];
var value = tempSortedList.Values[i];
Console.WriteLine("\t{0}:\t{1}", key, value);

How I get a Arraylist with not double values?

I want do get a Departmentlist from the Active Directory for this I use the Directoryentry and the DirectorySearcher class. I get the list of departments but how I can delete the double values in this list.
for example my list now:
it
it
it
vg
per
vg
...
And I want only one of this values in the list how this:
it
vg
per
...(other departments)
I want to use this list for a dropDownlist list.
my Code:
public static void GetAllDepartments(string domaincontroller)
{
ArrayList list = new ArrayList();
int Counter = 0;
string filter = "(&(objectClass=user)(objectCategory=user)(!userAccountControl:1.2.840.113556.1.4.803:=2)(sn=*)(|(telephoneNumber=*)(mail=*))(cn=*)(l=*))";
List<User> result = new List<User>();
DirectoryEntry Entry = new DirectoryEntry(domaincontroller);
DirectorySearcher Searcher = new DirectorySearcher(Entry, filter);
foreach (SearchResult usr in Searcher.FindAll())
{
result.Add(new User()
{
department = GetLdapProperty(usr, "Department")
});
Counter++;
}
for (int i = 0; i < Counter; i++)
{
list.Add(result[i].department);
}
}
How I can show only one value in the Arraylist?
First of all, I recommend that instead of using an ArrayList, use a Strongly-Typed list.
Then, use the Distinct() method to only get a list of unique values (no duplicates).
For instance:
List<String> list = new List();
....
for (int i = 0; i < Counter; i++)
{
list.Add(result[i].department.ToString());
}
var noDuplicates = list.Distinct();
Try Distinct() in System.Linq extensions :
list = list.Distinct();
You can also use the Exists clause to see if the element already exists in the list.
using System.Linq;
for (int i = 0; i < Counter; i++)
{
bool deptExists = list.Exists(ele => ele == result[i].department);
if(!deptExists){
list.Add(result[i].department);
}
}
Use the Enumerable.Distinct Method method.
Use a HashSet and only insert the non-duplicate values.
HashSet<string> list = new HashSet<string>();
...
for (int i = 0; i < Counter; i++)
{
string dep = result[i].department.ToString();
// true if dep was added, false if not. No exception at this point.
list.Add(dep);
}

adding items to a list in a dictionary

I'm trying to put values into a dictionary dependent on the key... For example, if in a list of keys at the index 0 there is a letter "a". I want to add the val with index 0 to a list inside of a dictionary with the key "a" ( dictionary (key is "a" at index 0 , val at index 0) ... dictionary (key is "b" at index 2 , val at index 2))
I'm expecting an output like this:
in listview lv1: 1,2,4 in listview lv2: 3,5
what I'm getting is 3,4,5 in both listviews
List<string> key = new List<string>();
List<long> val = new List<long>();
List<long> tempList = new List<long>();
Dictionary<string, List<long>> testList = new Dictionary<string, List<long>>();
key.Add("a");
key.Add("a");
key.Add("b");
key.Add("a");
key.Add("b");
val.Add(1);
val.Add(2);
val.Add(3);
val.Add(4);
val.Add(5);
for (int index = 0; index < 5; index++)
{
if (testList.ContainsKey(key[index]))
{
testList[key[index]].Add(val[index]);
}
else
{
tempList.Clear();
tempList.Add(val[index]);
testList.Add(key[index], tempList);
}
}
lv1.ItemsSource = testList["a"];
lv2.ItemsSource = testList["b"];
Solution:
replace the else code section with :
testList.Add(key[index], new List { val[index] });
thx everybody for your help =)
You are using the same list for both keys in the Dictionary
for (int index = 0; index < 5; index++)
{
if (testList.ContainsKey(key[index]))
{
testList[k].Add(val[index]);
}
else
{
testList.Add(key[index], new List<long>{val[index]});
}
}
Just create one new List(Of Long) when the key doesn't exists then add the long value to it
Get rid of the tempList and replace your else clause with:
testList.Add(key[index], new List<long> { val[index] });
And don't use Contains. TryGetValue is much better:
for (int index = 0; index < 5; index++)
{
int k = key[index];
int v = val[index];
List<long> items;
if (testList.TryGetValue(k, out items))
{
items.Add(v);
}
else
{
testList.Add(k, new List<long> { v });
}
}
Replace else with:
else
{
tempList.Clear();
tempList.Add(val[index]);
testList.Add(key[index], new List<long>(tempList));
}
The problem is, you are adding a reference to TempList to both keys, it is the same reference so it gets replaced in the first one.
I am creating a new list so it doesn't get replaced: new List<long>(tempList)
Sounds like a homework problem, but
for (int index = 0; index < 5; index++)
{
if (!testList.ContainsKey(key[index]))
testList.Add(key[index], new List<string> {value[index]});
else
testList[key[index]].Add(value[index]);
}
Read this (and the other relevant tutorials)
I'm not completely sure what you are trying to do here, but I guarantee you didn't want the same list in every dictionary entry.
templist is your problem swap templist.Clear() for templist = new List<Long>()
Or go for
for (int index = 0; index < 5; index++)
{
if (!testList.ContainsKey(key[Index]))
{
testList.Add(key[Index], new List<Long>());
}
testList[key[index]].Add(val[index]);
}

Categories