BligenN BligenN - 2 months ago 6
C# Question

C# Removing data from a list

So I have recently started working with C# and now I got a project to do at home...

I have a situation where I have a data file with information about an undefined amount of rings.... Their Maker, Name, Metal, Weight, Size, Purity and Price.

I've read the file... and separated the rings into a class which looks like:

class Rings
{
public string Maker { set; get; }
public string Name { set; get; }
public string Metal { set; get; }
public string Weight { set; get; }
public string Size { set; get; }
public string Purity { set; get; }
public string Price { set; get; }

public Rings() { }
public Rings(string maker, string name, string metal, string weight, string size, string purity, string price)
{
Maker = maker;
Name = name;
Metal = metal;
Weight = weight;
Size = size;
Purity = purity;
Price = price;
}
}


Now the final part of the project is to find and print to a file rings, which are under 300 in price and are either size 13 or 14... So I came up with the idea to make a loop and a couple of if functions to delete all rings which do not suit these requirements from the list, and then simply print out what's left of the list...
Here's the method:

public static void SpecificRings(List<Rings> RingList)
{

foreach(var x in RingList)
{
int ThePrice = int.Parse(x.Price);
int TheSize = int.Parse(x.Size);
if (ThePrice >= 300)
{
RingList.Remove(x);
}
else if (TheSize != 12 || TheSize != 13)
{
RingList.Remove(x);
}
}
}


Now the problem is that I do not know how to remove the actual things from the list... I understand that I'll need to make 7 of the RingList.Remove(); But how do I specify which information to delete? Any questions are welcome if I didn't explain the situation well enough

Answer

You're going to run into trouble here. Just to start with, you can't remove an item from a collection while you're enumerating the collection in a foreach loop.

        foreach(var x in RingList)
        {
            int ThePrice = int.Parse(x.Price);
            int TheSize = int.Parse(x.Size);
            if (ThePrice >= 300)
            {
//  >>> Exception will be throw on next line
                RingList.Remove(x);

The second proplem is that you've got one list of Rings, and you're removing items from it. Then they're gone. That can cause confusion.

There's a third problem:

if (TheSize != 12 || TheSize != 13)

That's not going to work well. Every ring is either not size 12, or not size 13. If it's 13, it's not 12; if it's 12, it's not 13. That line will discard everything.

I think you mean you want to keep only size 12 and size 13 rings, but that's a guess. Maybe you want to discard only size 12 and size 13? Let me know.

Here's a very simplified version of the function I would write to do what you're doing in SpecificRings. You say you're at a very early stage of learning, so I'll try to stick with stuff you've probably seen already.

First, if a function is getting specific rings, call it GetSpecificRings(). The compiler doesn't care, but it makes it easier to keep track of what your code is doing in your own mind.

But first, let's not use strings for everything:

class Rings
{
    public string Maker { set; get; }
    public string Name { set; get; }
    public string Metal { set; get; }
//  All these should be numbers
    public decimal Weight { set; get; }
    public decimal Size { set; get; }
    public decimal Purity { set; get; }
    public decimal Price { set; get; }

And now to get our specific rings:

public List<Rings> GetSpecificRings(List<Rings> rings)
{
    var rtn = new List<Rings>();

    foreach (var r in rings)
    {
        if (r.Price < 300 && (r.Size == 12 || r.Size == 13))
        {
            rtn.Add(r);
        }
    }

    return rtn;
}

Then you can call that function to get that subset of rings:

var myAffordableRingsInSomeSizes = GetSpecificRings(RingList);

I assume you're getting RingList from somewhere, like a database, or just statically initializing it. We can go into that further if we need to.

Here's another way to do the same thing, using stuff you may not have learned yet:

var sameResults = RingList.Where(r => 
            r.Price < 300 && (r.Size == 12 || r.Size == 13))
        ).ToList();

Take your pick.