C# Program to test efficient coding

You have several instances of the following class (User). Provide a class with three methods:
"AddUser" accepts a User instance as a parameter and add it to a collection.
"GetUser" accepts a UserID as a parameter and returns the corresponding User instance. It is important that this executes quickly as it will be used often.
"GetOrderedUserArray" returns an array of User instances ordered by UserID. It is important that this executes quickly as it will be used often.

public class User
{
public int UserID;
public string FamilyName;
public string GivenName;

public User(
int userID,
string familyName,
string givenName)
{
UserID = userID;
FamilyName = familyName;
GivenName = givenName;
}
}

Questions by netacct

Showing Answers 1 - 21 of 21 Answers

richa2008

  • Dec 4th, 2008
 

public NewClass()
{
 
 
  public  Arraylist m_Arrusers;
public void AddUser(User objser)
{


  m_arrusers.Add(objUser);
 

}

public User GetUser(int UserID)
{
   User obj;
  for( int i=0; i<m_ArrUsers.GetCount();i++)
  {
    obj=(User)m_ArrUsers[i];
    if(obj.Userid==userID)
      return obj;
 
  }

}


  Was this answer useful?  Yes

Farohar

  • Jan 22nd, 2009
 

If at an interview I would certainly have failed. Took me far to long to implement the sort. Also I have no clue weather this is efficient or not - all I know is that it works ...

using System;
using System.Collections;

namespace user
{
    class Program
    {
        static void Main(string[] args)
        {
            UserList uList = new UserList();

            for (int i = 100; i > 0; i--)
                uList.AddUser(new User(i, "FName", "GName"));

            Console.WriteLine(uList.GetUser(2).FamilyName);

            foreach (User u in uList.GetOrderedUserArray())
                Console.WriteLine("ID: {0} FName: {1} GName: {2}",
                                    u.UserID,
                                    u.FamilyName,
                                    u.GivenName);
            Console.ReadKey();
        }
    }

    public class User : IComparable
    {
        public int UserID;
        public string FamilyName;
        public string GivenName;

        // default (ascending) sort
        int IComparable.CompareTo(Object obj)
        {
            User uid1 = (User)this;
            User uid2 = (User)obj;
            if (uid1.UserID < uid2.UserID) return 1;
            if (uid1.UserID > uid2.UserID) return -1;
            else return 0;
        }

        public User(int userID, string familyName, string givenName)
        {
            UserID = userID;
            FamilyName = familyName;
            GivenName = givenName;
        }
    }

    // do descending sort on UserID property.
    public class sortUIdDescendingHelper : IComparer
    {
        int IComparer.Compare(Object a, Object b)
        {
            User uid1 = (User)a;
            User uid2 = (User)b;
            if (uid1.UserID > uid2.UserID) return 1;
            if (uid1.UserID < uid2.UserID) return -1;
            else return 0;
        }
    }

    // the class holding our new three methods
    public class UserList
    {
        ArrayList userList = new ArrayList();

        public void AddUser(User user) { userList.Add(user); }

        public User GetUser(int userID)
        {
            foreach (User u in userList)
                if (u.UserID == userID) return u;
            return (User)userList[0];
        }

        public ArrayList GetOrderedUserArray()
        {
            IComparer myComparer = new sortUIdDescendingHelper();
            // userList.Sort() // default (descending) sort
            userList.Sort(myComparer);  // ascending sort
            return userList;
        }
    }
}

  Was this answer useful?  Yes

Farohar

  • Jan 24th, 2009
 

Actually the code can be a lot more efficient. First of all, instead of using ArrayList one should use List<T>. That way we would not need to create a new ArrayList just to find a certain item in the array. We would just access the item via "listname[n]". That is, instead of:


        public User GetUser(int userID)
        {
            foreach (User u in userList)
                if (u.UserID == userID) return u;
            return (User)userList[0];
        }

we do

        public User GetUser(int userID) { return userList[userID]; }

which is still not perfect as every time we access this method a new instance of the class User is created. Instead of doing it that way I would just access the list directly via "uList.userList[n].value".

Also I would not create a method "GetOrderedUserArray()" of type List<User> as calling it creates another list in memory. Now why would we need another memory consuming list if we got one already? Considering the method is supposedly called often it makes even less sense to design it that way. To sort the list we do not have to create a new list, sort it and return it (or rather, as I did it in the first example, sort our existing list, copy it to a new list and return that). Just sort the existing one and we're done. So instead of doing

            foreach (User u in uList.GetOrderedUserArray())
                Console.WriteLine("ID: {0} FName: {1} GName: {2}",
                                    u.UserID,
                                    u.FamilyName,
                                    u.GivenName);

which creates a new instance of the class "User" and also creates a new "List<User>", we could just access those list items via

            uList.userList.Sort();
            for (int i = 0; i < uList.userList.Count; i++)
                Console.WriteLine("ID: {0} FName: {1} GName: {2}",
                    uList.userList[i].UserID,
                    uList.userList[i].FamilyName,
                    uList.userList[i].GivenName);

which uses our existing "List<User>" and does not need to instanciate a new class "User" either.

This means: two of the methods we were supposed to code are simply gone! We dont actually need them or rather dont even want them. The inherited function "Sort()" replaces "GetOrderedUserArray()" and instead of returning a new User instance with "GetUser()" we access the List directly to get our hands at its items.

This is not only more efficient memory wise, it also is less code and less methods. Here the full code:

----- 8< ----- 8< ----- 8< ----- 8< ----- 8< ----- 8< -----

using System;
using System.Collections.Generic;

namespace UserSort
{
    class Program
    {
        static void Main(string[] args)
        {
            UserList uList = new UserList();
            
            for (int i = 100; i >= 0; i--)
                uList.AddUser(new User(i, "FName" + i, "GName" + i));

            uList.userList.Sort();
            for (int i = 0; i < uList.userList.Count; i++)
                Console.WriteLine("ID: {0} FName: {1} GName: {2}",
                    uList.userList[i].UserID,
                    uList.userList[i].FamilyName,
                    uList.userList[i].GivenName);
            Console.ReadKey();
        }
    }

    public class User : IComparable
    {
        public int UserID;
        public string FamilyName;
        public string GivenName;

        // default (ascending) sort
        int IComparable.CompareTo(Object obj)
        {
            User uid1 = (User)this;
            User uid2 = (User)obj;
            if (uid1.UserID < uid2.UserID) return 1;
            if (uid1.UserID > uid2.UserID) return -1;
            else return 0;
        }

        public User(int userID, string familyName, string givenName)
        {
            UserID = userID;
            FamilyName = familyName;
            GivenName = givenName;
        }
    }

    // the class holding our new three methods (rather one method now ... =)
    public class UserList
    {
        public List<User> userList = new List<User>();
        public void AddUser(User user) { userList.Add(user); }
    }
}

----- >8 ----- >8 ----- >8 ----- >8 ----- >8 ----- >8 -----

I know it has been a long answer off a previous and long answer by myself. Nevertheless I believed it proper to post it as the way C# works it just far too easy to not care about how many resources an application is instanciating. One could argue "Well, the garbage collecter will handle all this!", but then: more efficient is more efficient, garbage collector or not.

  Was this answer useful?  Yes

broli

  • Aug 1st, 2009
 

Here's an easy way to take care of the sorting part by using the new Linq feature in .NET 3.5

Assuming you have an ArrayList with all the user objects.

ArrayList array = new ArrayList();
Add all the user objects...........

//Arraylist isn't supported by Linq so you must specify type
var linq = array.OfType<User>();
var sort = from i in linq orderby i.UserID select i;

Now the arraylist "sort" will contain all the objects sorted by user id.

  Was this answer useful?  Yes

virtuallad

  • Nov 29th, 2009
 

Guys, I am afraid that you are missing the key point here: GetUser() and GetOrderedUserArray() methods should be as fast as possible. We can make them run in O(1) if we add the pre-processing at the AddUser() method.

// the class holding our new three methods
public class UserList
{
List<User> userList = new List<User>();
Dictionary<int, User> userDictionary = new Dictionary<int, User>();

public void AddUser(User user)
{
  userList.Add(user);
  IComparer myComparer new sortUIdDescendingHelper();
  // userList.Sort() // default (descending) sort
  userList.Sort(myComparer); // ascending sort

  userDictionary[user.id] =
user;

}

public User GetUser(int userID) { return userDictionary[userID]; }

public List<User> GetOrderedUserArray() { return userList; }
}

asaf122

  • Jan 28th, 2010
 

class UserManager
    {
        private List<User> list;

        internal List<User> List
        {
            get { return list; }
            set { list = value; }
        }

        public UserManager()
        {
            list = new List<User>();
        }

        public void Add(User usr)
        {
            list.Add(usr);
        }

        public User GetUsrById(int id)
        {
            foreach (User usr in list)
            {
                if (usr.UserID == id)
                    return usr;
            }

            return null;
        }

        public User[] GetOrderedUserArray()
        {
            list.Sort();
            return list.ToArray();
        }
    }



class User :IComparable
    {
        public int UserID;
        public string FamilyName;
        public string GivenName;

        public User(int userID, string familyName, string givenName)
        {
            UserID = userID;
            FamilyName = familyName;
            GivenName = givenName;
        }

        #region IComparable Members

        public int CompareTo(object obj)
        {
            if (!(obj is User))
                throw new ArgumentException("Must be Usr", "obj");

            User u = (User)obj;
            return this.UserID.CompareTo(u.UserID);
        }

        #endregion
    }

  Was this answer useful?  Yes

jankajg

  • Sep 25th, 2010
 

@asaf122 - your method can be improved a bit by using list. Find even better
by lambda expressions) here is how


class UserManager

{

private List list;


internal List List

{

get { return list; }

set { list value; }

}


public UserManager()

{

list new List();

}


public void Add(User usr)

{

list.Add(usr);

}


public User GetUsrById(int id)

{


//method 1

list.Find(delegate(int id)

{

return list.Equals(id);

});


//method 2

list.Find((int id)

=> list

.Equals(id));


}


public User[] GetOrderedUserArray()

{

list.Sort();

return list.ToArray();

}

}



class User :IComparable

{

public int UserID;

public string FamilyName;

public string GivenName;


public User(int userID string familyName string givenName)

{

UserID userID;

FamilyName familyName;

GivenName givenName;

}


#region IComparable Members


public int CompareTo(object obj)

{

if (!(obj is User))

throw new ArgumentException("Must be Usr" "obj");


User u (User)obj;

return this.UserID.CompareTo(u.UserID);

}


#endregion

}


  Was this answer useful?  Yes

Give your answer:

If you think the above answer is not correct, Please select a reason and add your answer below.

 

Related Answered Questions

 

Related Open Questions