-1
 Random rand = new Random();
        var list = new object[] { 1, 2, 3, "A", "B", "C" };
        object item = list[rand.Next(0, list.Length)];

I want to return item then remove it from list[]

Lenny G
  • 25
  • 1
  • 1
  • 3
  • 1
    The item can be "removed" by assigning a sentinel value (ie. null, and possibly sliding other values over), however *the size of an array cannot be changed in .NET*. A new array can be created .. and all this is to say, a `List` (or changing the mutable requirement) is probably what is being looked for. Internally a List uses arrays, creating larger arrays and sliding values as required. – user2864740 Dec 21 '16 at 21:02
  • 1
    Arrays don't work that way. You would need to copy the array (minus the removed element) to a new array that is one less in length. But that's horribly inefficient, which is why `List` exists. Unless an array has a fixed length that isn't going to change, use `List` instead. – Matt Burland Dec 21 '16 at 21:02

7 Answers7

6

You can't. Use List<object> instead.

var list = new List<Object> { 1, 2, 3, "A", "B", "C" };

or

var list = (new object[] { 1, 2, 3, "A", "B", "C" }).ToList();

Or even

var list = new List<Object>(new object[] { 1, 2, 3, "A", "B", "C" });

Then to remove an item (note that Length changes to Count):

int idx = rand.Next(0, list.Count);

object item = list[idx];

list.RemoveAt(idx);

There's also a Remove method:

list.Remove(item);

In a case where you know there are no duplicates in the list (like this one), that's fine too.

The closest you could come to "removing" an item from an array is to create a new array without it -- certainly not worth the trouble.

List<T> is much more versatile than arrays, so we generally use it instead.

  • 1
    List has a .Remove() that can be used. – Bauss Dec 21 '16 at 21:16
  • @Bauss - if you already have the index then that should be used as its more efficient. So yes, it has a .Remove() method but RemoveAt is preferred in this case. – Igor Dec 21 '16 at 21:18
  • @Bauss That's true. They can also have duplicate items (though obviously not in this case), and anyway since we're identifying the item by index, I figured I'd just run with that. But I added your suggestion as well. – 15ee8f99-57ff-4f92-890c-b56153 Dec 21 '16 at 21:24
1

You have to destroy (forget) and recreate the array.

Random rand = new Random();
var list = new object[] { 1, 2, 3, "A", "B", "C" };
var index = rand.Next(0, list.Length);
object item = list[index];
list = list.Where((x, y) => y != index).ToArray(); // create new array and reassign to the existing reference
return item;

There is no good reason to do this though, use a List<T> instead. Here is that same code using a List<object>

Random rand = new Random();
var list = new List<object> { 1, 2, 3, "A", "B", "C" };
var index = rand.Next(0, list.Count);
object item = list[index];
list.RemoveAt(index);
return item;
Igor
  • 60,821
  • 10
  • 100
  • 175
1

There's some misinformation here. I agree with that you should use a list, however people forget that a list just wraps around arrays.

Basically you can remove from an array like this:

void Remove<T>(ref T[] source, T value)
    where T : IComparable
{
    var newArray = new T[source.Length];
    var index = 0;

    foreach (var item in source)
    {
        if (item.CompareTo(value) == 0) continue;

        newArray[index]  = item;
        index++;
    }

    Array.Resize(ref newArray, index);
    source = newArray;
}

Usage example:

var array = new[] { 1, 2, 3, 4 };

Remove(ref array, 2);

array.Dump();

It's not pretty, but neither are lists behind the scene, because arrays aren't using dynamic allocations in .NET.

Bauss
  • 2,767
  • 24
  • 28
0

As others mentioned you cannot "delete" from an array (changing its size) but you can instead assign an array object (i.e. list[0] = null) and check for null while processing the array.

Arrays are nice but truly Lists are so much more flexible and allow the "Remove' method. Add items using List.Add("item") and remove using List.Remove("item"). It allows most of the other array functionality for most basic usage too including List.Count, List.Distinct, List[numeral], etc.

pizzaslice
  • 478
  • 2
  • 8
0

To build off of what @Ed Plunkett said. I would change your code to this:

Random rand = new Random();
var list = new List<object> { 1, 2, 3, "A", "B", "C" };
object item = list[rand.Next(0, list.Count - 1)];

Then you call the Remove method to remove the object.

list.Remove(object);

Sidenote: Note that I changed your parameters for the rand.Next method. If you set the max possible number to be the number of items in the list, you could potentially hit an IndexOutOfBounds exception. Lists use a zero based index, so if you have 45 items in the list, the last one would actually be at index 44.

Kyle Rone
  • 305
  • 1
  • 14
0

If you need a collection with dynamic length (i.e. length that potentially changes because items are added and/or removed) then you should use List<T>. So your code could be something like:

Random rand = new Random();
var list = new List<object> { 1, 2, 3, "A", "B", "C" };
var idx = rand.Next(0, list.Count);
object item = list[idx];
list.RemoveAt(idx);

Arrays are supposed to be fixed length. If you need to modify the length on an array you would have to create a new array (with the updated length) and copy all the elements (minus the removed item) into the new array. This is very inefficient. There aren't too many cases where an array is a better choice than a List.

Matt Burland
  • 44,552
  • 18
  • 99
  • 171
0

Java has a dynamic array class, which it seems like is sort of what you want, but C# doesn't have a "built-in" exact equivalent; the closest equivalent is List<T> (see this answer for more details).

Keep in mind how an array works "under the hood" (and I'm simplifying here a little) - when you allocate it, the runtime "knows" to lay out a certain number of consecutive memory spaces. In C/C++ (and decedent languages are generally doing something similar), the runtime's storing a pointer/reference to the first item in the array. You can then calculate the memory address of an arbitrary item in the array in constant time - for example, if the first address is 1000 and addresses are 32 bits, the 3rd item will be at address 1000 + (2 * 32) = 1064.

Incidentally, that's why arrays are indexed at zero - the address of the first item in the array is the pointer/reference to the beginning of the array plus zero offset.

The issue, then, is if you deleted some item in the middle of the array the memory locations would no longer be consecutive. If you delete someArray[3] and then tried to access that later, what exactly should happen? Should it become null, become a de facto uninitialized memory location, or contain whatever used to be at someArray[4]?

Community
  • 1
  • 1