简体   繁体   中英

C# inserting numbers into a list box in sorted position

Excuse my nooby first post please. I am having an issue with a univerity assignment. The assignment is a "Number list manager", basically user chooses a radio button (sorted or unsorted) and when they click a button 30 numbers will be added to a list box respecting the users choice. I have no issue with the unsorted code. The lecturer specifically wants us to add the sorted numbers into the list and sort them as they are being added rather than generate the whole list and then sorting it.

if (radUnsorted.Checked == true)//if unsorted
{
    RunChecks();
    do
    {
        numberToInput = (rnd.Next(0, 100));//sets number to input to random number
        int i = 1;

        while (i < lstNumbers.Items.Count)//loops though whole list
        {
            if (numberToInput == ConvertToInt32(lstNumbers.Items[i]))//checks that number doesnt already exist in list
            {
                numberToInput = (rnd.Next(0, 101));//genrate new random number
                i = 0;//set to 0 to restart checking through the list
            }
            else//if the number isnt at i index
            {
                i++;//move onto next number
            }
        }

        lstNumbers.Items.Insert(i - 1, numberToInput);//insert the number
        RunChecks();//check if the list is full

    } while (spaceLeft == true);//keep looping untill list is full
}

This is my code to add numbers to the list in unsorted position. I've tried looking online but the only method i can see is a for loop to add the numbers to the list and then another for loop to sort them.

Here is a snippet of the criteria: You must manipulate the list during inserts and deletes using your own code and not must not utilise C# methods which undertake the task automatically eg inserting into an unsorted list merely requires the new value to be placed in the next available location after the current last entry whilst inserting into a sorted list requires your code to locate the insertion point and move any higher value entries to open/free up the insertion point for the inclusion of the new value.

I'm not asking for anyone to do the work for me but even pseudo-code would be very appreciated

Okay, first of all I'm not sure what these checks for the list being full is all about, can't you just clear the items each time you press the button and iterate through 1 to 30?

Anyway, here's some code I knocked up for both sorted and unsorted:

private void unsorted_Click(object sender, EventArgs e)
{
    lstNumbers.Items.Clear(); //clear any existing numbers, and add a new 30.
    var rand = new Random();
    for (var i = 0; i < 30; i++)
    {
        var randNumber = rand.Next(0, 100);
        while (lstNumbers.Items.Contains(randNumber))
        {
            //generate new number until it's unique to the list.
            randNumber = rand.Next(0, 100);
        }
        lstNumbers.Items.Add(randNumber);
    }
}

private void sorted_Click(object sender, EventArgs e)
{
    lstNumbers.Items.Clear(); //clear any existing numbers, and add a new 30.
    var rand = new Random();
    for (var i = 0; i < 30; i++)
    {
        var randNumber = rand.Next(0, 100);
        while (lstNumbers.Items.Contains(randNumber))
        {
            //generate new number until it's unique to the list.
            randNumber = rand.Next(0, 100);
        }

        if (lstNumbers.Items.Count == 0)
        {
            //we have no items, obviously the default position would be 0.
            lstNumbers.Items.Add(randNumber);
            continue; //next iteration
        }

        //find out the sorted position
        var bestPos = 0;
        for (var j = 0; j < lstNumbers.Items.Count; j++) //loop through the current list.
        {
            var currValue = Convert.ToInt32(lstNumbers.Items[j]);
            if (randNumber > currValue)
            {
                bestPos = j + 1;
            }
            else
            {
                bestPos = j;
                break; //we no longer need to check, it will never be any less than this.
            }
        }
        if (bestPos < 0)
            bestPos = 0;
        lstNumbers.Items.Insert(bestPos, randNumber);
    }
}

You're already iterating through the list and reading each value, so all you need to do is check if the existing value is larger than the one you're inserting. If so, you should insert it before the item you've just checked.

            var inserted = false;
            while (i < lstNumbers.Items.Count)//loops though whole list
            {
                if (numberToInput == Convert.ToInt32(lstNumbers.Items[i]))//checks that number doesnt already exist in list
                {
                    numberToInput = (rnd.Next(0, 101));//genrate new random number
                    i = 0;//set to 0 to restart checking through the list
                }
                else if (numberToInput < Convert.ToInt32(lstNumbers.Items[i])
                {
                    lstNumbers.Items.Insert(i - 1, numberToInput);//insert the number
                    inserted = true;
                } 
                else//if the number isnt at i index
                {
                    i++;//move onto next number
                }
            }

            if (!inserted)
            { 
                lstNumbers.Items.Insert(i - 1, numberToInput);//insert the number
            }

Note the check for when the new item needs to go at the end of the list.

I imagine this is what your teacher wants, and it's important to understand how to work with arrays, but really the best way to sort a list in C# is not to use an array but a List or other class that has it's own sorting method.

        var myList = new List<int>();
        myList.Add(5);
        myList.Add(3);
        myList.Add(1);

        myList.Sort();

This would be faster and more efficient if you had a million items, and it would work for strings or dates or whatever.

List also has a Contains method, and several other shortcuts that make life easier. @ThePerplexedOne is right that this sorts after the list is populated, you could use a SortedList , which would automatically insert items in the right place.

I make perhaps more simple way to solve this problem using SortedList .

SortedList<int, object> sortedList = new SortedList<int, object>();

sortedList.Add(4, null);
sortedList.Add(1, null);
sortedList.Add(7, null);

foreach(KeyValuePair<int, object> k in sortedList)
{
    Console.WriteLine(k.Key);
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM