Link to home
Start Free TrialLog in
Avatar of mikha
mikhaFlag for United States of America

asked on

List in C#

Example Contrived for the question.
Say, I have a list<string>  of addresses. I check each value to see, if certain conditions meet and if yes, i change the value and save it back to
the list.
I was using a foreach loop, but realized since it returns an enumerator,which is readonly, I  can't modify the list with foreach loop.
now I changed it to for loop.

my question is, is there any other(better) alternative or data structure to use for better performance, if we have to iterate through
millions of addresses.


List<string> addresses = new List<string>();
        addresses .Add("1280 Kenwood ave");
        addresses .Add("14 main st");
        addresses .Add("925 keene road");
        addresses .Add("42 lee street");

            for (int i = 0; i < addresses .Count; i++) {
                var add = addresses[i].ToString(); 

                if (add.Contains("st")) {
                    add.Replace("st", "Street") ; 
                }
                addresses[i] = add; 
            }

Open in new window

Avatar of Norie
Norie

Perhaps you could use Linq?
var newadresses = from addr in addresses
                              select addr.Replace(" st", " street");

addresses =  newadresses.ToList();

Open in new window

As you are having to check every adress then any other collection would not offer advantages.
ASKER CERTIFIED SOLUTION
Avatar of kaufmed
kaufmed
Flag of United States of America image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
You mention "millions of address". Just out of curiosity, where are they coming from in C#. And how many such modifications are you intending to perform? And is it one time task or repetitive?

This is important, as it is better to perform such tasks nearest to the origin of data, if possible.

Apologies for commenting on your question with a question. However, sometimes it is important to question the premise. Take no offence, please!
Rather than looping through your objects, it would make more sense to inherit the List and override the add method to impose rules on your added objects (which I believe is what Nitin is ultimately alluding to); e.g. -
using System;
using System.Collections.Generic;
using System.Linq;

namespace EE_Q29043011
{
    class Program
    {
        static void Main(string[] args)
        {
            var addresses = new Addresses
            {
                new Address { Street = "1280 Kenwood ave" },
                new Address { Street = "14 main st" },
                new Address { Street = "925 keene road" },
                new Address { Street = "42 lee street" },
            };

            foreach (var address in addresses)
                Console.WriteLine(address.Street);
            Console.ReadLine();
        }
    }

    class Addresses : List<Address>
    {
        public new void Add(Address address)
        {
            if (address.Street.Split(' ').Contains("st", StringComparer.OrdinalIgnoreCase))
                address.Street = address.Street.Replace("st", "Street");
            base.Add(address);
        }
    }

    class Address
    {
        public string Street { get; set; }
    }
}

Open in new window

Produces the following output -User generated image
-saige-
SOLUTION
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
@it_saige

But you're not really overriding...you're method hiding. If you had the following:

List<Address> addresses = new Addresses();

Open in new window


...which is perfectly valid, then your new method is no longer enforced. Common wisdom on the web is that you should not inherit directly from List<T>, and instead should implement one of the generic interfaces or abstract classes like Collection or IList.
SOLUTION
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Parsing and checking before adding to a collection is good (IMHO should be done by any one writing code).
My understanding of the question however is given an existing collection of eg. a list which, if any, collection would offer advantages when checking every element and performing an action on the contents.  
Maybe the author could supply feedback as to just what direction the question should be going in.
AFAIK, the best you could do performance-wise would be constant time (i.e. O(n)) no matter which data structure you use. The only way to beat that would be employ some kind of parallel processing (e.g. threads), but even then it's still just O(n) (just a smaller n). If you have to operate on every item in the list, then you have to iterate over the entire list. If you're searching for items that meet specific criteria, then you can employ various data structures to make your search more efficient.
Avatar of mikha

ASKER

Thank you all for your excellent comments. My primary question primarily, when dealing with large number of addresses, was there any better
data structure or search and replace methods that i can use. but i found my answer.

@käµfm³d - you pointed out something, that I didn't think of about the string, that it is  immutable . out of curiosity. like i mentioned in original
post. say if i have  the same code. I use just a for loop and create a new variable newAddress (this is just for the sake of example below). I modify the original  address and save it to newAddress and then save the newAddress to the index i.

this should technically work, right? since i'm just replacing the contents of the list at index i .

List<string> addresses = new List<string>();
        addresses .Add("1280 Kenwood ave");
        addresses .Add("14 main st");
        addresses .Add("925 keene road");
        addresses .Add("42 lee street");

        string newAddress;

            for (int i = 0; i < addresses .Count; i++) {

                var oldAdd = addresses [ i ].ToString();    //old address

                if (add.Contains("st")) {
                    newAddress = oldAdd .Replace("st", "Street") ;  //modify old address and save it to newAddress
                }

                addresses  [ i ]= newAddress ; //replace the list content at index i
            }
SOLUTION
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
I would suggest one minor change (unless you want to end up with an entry for - 42 lee Streetreet) -
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;

namespace EE_Q29043011
{
    class Program
    {
        static void Main(string[] args)
        {
            List<string> addresses = new List<string>();
            addresses.Add("1280 Kenwood ave");
            addresses.Add("14 main st");
            addresses.Add("925 keene road");
            addresses.Add("42 lee street");

            for (int i = 0; i < addresses.Count; i++)
            {
                if (addresses[i].Split(' ').Contains("st", StringComparer.OrdinalIgnoreCase))
                    addresses[i] = addresses[i].Replace("st", "Street");
            }

            foreach (var address in addresses)
                Console.WriteLine(address);

            Console.ReadLine();
        }
    }
}

Open in new window

Which produces the following output -User generated image
-saige-
Well, the immutability I was referring to in my original comment had more to do with saying you can't simply say something like:

int someIndex = 0;
string someString = "Hello World!";

someString[someIndex] = 'c';

That's just due to how strings work. The short of it is:  If you use a for loop, then you shouldn't have any problems. (Unless, of course, you start removing things from the list. In that case you have to use a reverse for loop.)