Go Premium for a chance to win a PS4. Enter to Win

x
?
Solved

How to divide a big C# SortedList into smaller SortedLists?

Posted on 2010-11-10
17
Medium Priority
?
666 Views
Last Modified: 2012-08-14
Hi,

I have to send out emails using a script. Exchange server has a limit of 25 emails (cannot change, its company policy).

My code is:
SendEmails (slAddresses[_key].ToString());

I will appreciate if someone can please post code to divide the SortedList into multiple SortedLists (if the slAddresses has more than 25 records) and use same method multiple times to perform this.

Thanks in advance.

H
0
Comment
Question by:m_a_n
  • 7
  • 5
  • 4
  • +1
17 Comments
 
LVL 75

Expert Comment

by:käµfm³d 👽
ID: 34105954
I believe this will suit you. You can change the types on each SortedList to fit your code (I used strings).
public SortedList<string, string>[] GetSmallerLists(SortedList<string, string> sourceList)
{
    const int MAX_SIZE = 25;
    SortedList<string, string>[] smallerLists = new SortedList<string, string>[(sourceList.Count % MAX_SIZE) + 1];
    int i;
    int j = 0;

    for (i = 0; i < smallerLists.Length; i++) smallerLists[i] = new SortedList<string, string>(MAX_SIZE);

    i = 0;

    foreach (string key in sourceList.Keys)
    {
        smallerLists[j].Add(key, sourceList[key]);

        i++;

        if (i == MAX_SIZE)
        {
            j++;
            i = 0;
        }
    }

    return smallerLists;
}

Open in new window

0
 
LVL 75

Expert Comment

by:käµfm³d 👽
ID: 34105981
P.S.

You would then process the resulting array as:
SortedList<string, string> slAddresses = new SortedList<string, string>();
SortedList<string, string>[] smallerLists = GetSmallerLists(slAddresses);

foreach (SortedList<string, string> list in smallerLists)
{
    // Mail current list
    foreach (string _key in list)
    {
        SendEmails(list[_key].ToString());
    }
}

Open in new window

0
 

Author Comment

by:m_a_n
ID: 34106083
Thanks there, unfortunately I get this error.

The non-generic type 'System.Collections.SortedList' cannot be used with type arguments.

Any thoughts?

Really appreciated.
0
Concerto Cloud for Software Providers & ISVs

Can Concerto Cloud Services help you focus on evolving your application offerings, while delivering the best cloud experience to your customers? From DevOps to revenue models and customer support, the answer is yes!

Learn how Concerto can help you.

 

Author Comment

by:m_a_n
ID: 34106100
// The error is for this line:

public SortedList<string, string>[] GetSmallerLists(SortedList<string, string> sourceList)
0
 
LVL 3

Expert Comment

by:yanoch
ID: 34106387
Hi friend,

try this!

      private void Form1_Load()
      {
            SortedList slAdresses = new SortedList();
            for (int i = 1; i <= 100; i++)
            {
                slAdresses.Add(i.ToString(), string.Format("Adress #{0}", i.ToString()));
            }
            foreach (SortedList lst in SplitList(slAdresses, 25))
            {
                //SendEmail(lst);
                Console.WriteLine(lst.Count); //all lists have 25 in them..
            }
       }

        private List> SplitList(SortedList SL, int Max)
        {
            if (SL.Count <= Max)
                return new List>() { SL };

            List> retVal = new List>();
            SortedList tmpLst = new SortedList();

            foreach (KeyValuePair kvp in SL)
            {
                tmpLst.Add(kvp.Key, kvp.Value);
                if (tmpLst.Count > Max - 1)
                {
                    retVal.Add(tmpLst);
                    tmpLst = new SortedList();
                }
            }

            return retVal;
        }

I think with that code you can get it to work your way!
bye!
0
 

Author Comment

by:m_a_n
ID: 34106431
To: kaufmed

Thanks buddy I needed to have using System.Collections.Generic; to not get any build errors.

I will test this code and let you know.

Thanks vanoch for your efforts as well.

Will come back soon!
0
 
LVL 75

Expert Comment

by:käµfm³d 👽
ID: 34106665
>>  using System.Collections.Generic

That is absolutely correct. Sorry for not pointing it out. I sometimes forget that there are non-generic versions of most of the collections in .NET  :)
0
 

Author Comment

by:m_a_n
ID: 34106704
Thanks Kaufmed, I think we are very close:

Now the only error I get is:

"Cannot convert type 'System.Collections.Generic.KeyValuePair<string,string>' to 'string'"

As my SortedList is a non-generic version.

Any changes you would suggest?

Thanks a lot.
0
 
LVL 33

Expert Comment

by:Todd Gerbert
ID: 34106768
Instead of actually splitting the list, why not just loop through it 25 items at a time (I used a List<string> in my example to hold all the addresses)?
class Program
	{
		static void Main(string[] args)
		{
			List<string> emails = new List<string>();

			// Create a dummy list of e-mail addresses just for testing
			for (int i = 0; i < 100; i++)
				emails.Add("address" + i.ToString());

			SendEmails(emails);
		}

		static void SendEmails(List<string> Addresses)
		{
			int groups = Addresses.Count / 25;

			for (int i = 0; i < groups; i++)
			{
				MailMessage message = new MailMessage();
				for (int j = 0; j < 25; j++)
				{
					message.To.Add(Addresses[i + j]);
				}
				smtp.Send(message);
			}
		}
	}

Open in new window

0
 
LVL 33

Expert Comment

by:Todd Gerbert
ID: 34106788
Oops, I made a boo-boo!  Line 23 should read:
message.To.Add(Addresses[j + (i * 25)]);
0
 
LVL 33

Expert Comment

by:Todd Gerbert
ID: 34106879
I'm not as clever as I thought. ;)
You also need to account for instances when the list isn't evenly divisible my the number of addresses, i.e. with 26 addresses divided by 25 = 1, but you need two messages for the 26th address.
I just wrote string to console for testing, but you get the idea!

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.Net.Mail;

namespace ConsoleApplication1
{
	class Program
	{
		static void Main(string[] args)
		{
			List<string> emails = new List<string>();

			// Create a dummy list of e-mail addresses just for testing
			for (int i = 0; i < 16; i++)
				emails.Add("address" + i.ToString());

			SendEmails(emails, 5);
			Console.ReadKey();
		}

		static void SendEmails(List<string> Addresses, int maxPerMessage)
		{
			int groups = Addresses.Count / maxPerMessage;
			int remainder = Addresses.Count % maxPerMessage;
			for (int i = 0; i < groups; i++)
			{
				Console.WriteLine("\r\n\r\nStarting new message...");
				for (int j = 0; j < maxPerMessage; j++)
				{
					Console.WriteLine(Addresses[j + (i * maxPerMessage)]);
				}
			}

			if (remainder > 0)
			{
				Console.WriteLine("Last message...");
				for (int i = 0; i < remainder; i++)
				{
					Console.WriteLine(Addresses[(groups * maxPerMessage) + i]);
				}
			}
		}
	}
}

Open in new window

0
 
LVL 75

Expert Comment

by:käµfm³d 👽
ID: 34107131
Converted to non-generic form:
public SortedList[] GetSmallerLists(SortedList sourceList)
{
    const int MAX_SIZE = 25;
    SortedList[] smallerLists = new SortedList[(sourceList.Count % MAX_SIZE) + 1];
    int i;
    int j = 0;

    for (i = 0; i < smallerLists.Length; i++) smallerLists[i] = new SortedList(MAX_SIZE);

    i = 0;

    foreach (string key in sourceList.Keys)
    {
        smallerLists[j].Add(key, sourceList[key]);

        i++;

        if (i == MAX_SIZE)
        {
            j++;
            i = 0;
        }
    }

    return smallerLists;
}

Open in new window

0
 
LVL 75

Accepted Solution

by:
käµfm³d   👽 earned 2000 total points
ID: 34107207
Slight correction:  I shouldn't have used the MOD operator; simple division is what was needed. I am also including an updated usage example:
public static SortedList[] GetSmallerLists(SortedList sourceList)
{
    const int MAX_SIZE = 25;
    SortedList[] smallerLists = new SortedList[(sourceList.Count / MAX_SIZE) + 1];
    int i;
    int j = 0;

    for (i = 0; i < smallerLists.Length; i++) smallerLists[i] = new SortedList(MAX_SIZE);

    i = 0;

    foreach (string key in sourceList.Keys)
    {
        smallerLists[j].Add(key, sourceList[key]);

        i++;

        if (i == MAX_SIZE)
        {
            j++;
            i = 0;
        }
    }

    return smallerLists;
}


// usage
SortedList[] smallerLists = GetSmallerLists(slAddresses);

foreach (SortedList list in smallerLists)
{
    // Mail current list
    foreach (object _key in list.Keys)
    {
        Console.WriteLine(list[_key].ToString());
    }
}

Open in new window

0
 
LVL 33

Expert Comment

by:Todd Gerbert
ID: 34107215
Haha...I was just about to call you on that. ;)
Was going to suggest:
SortedList[] smallerLists = new SortedList[sourceList.Count / MAX_SIZE + (sourceList.Count % MAX_SIZE == 0 ? 0 : 1)];
0
 
LVL 75

Expert Comment

by:käµfm³d 👽
ID: 34107590
>>  Haha...I was just about to call you on that. ;

Good thing I'm quick  ;)

In my example, MAX_SIZE is a const value, as opposed to your parameterized version, so that would be irrelevant for mine--unless someone was crazy enough to make zero the const value!
0
 

Author Closing Comment

by:m_a_n
ID: 34111837
Thanks a lot Kafumed. It was just perfect.

Others' efforts would have been good as well, though I did not try them.

Thanks all of you.
0
 
LVL 75

Expert Comment

by:käµfm³d 👽
ID: 34115785
NP.  Glad to help :)
0

Featured Post

What does it mean to be "Always On"?

Is your cloud always on? With an Always On cloud you won't have to worry about downtime for maintenance or software application code updates, ensuring that your bottom line isn't affected.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Article by: Najam
Having new technologies does not mean they will completely replace old components.  Recently I had to create WCF that will be called by VB6 component.  Here I will describe what steps one should follow while doing so, please feel free to post any qu…
Summary: Persistence is the capability of an application to store the state of objects and recover it when necessary. This article compares the two common types of serialization in aspects of data access, readability, and runtime cost. A ready-to…
Want to learn how to record your desktop screen without having to use an outside camera. Click on this video and learn how to use the cool google extension called "Screencastify"! Step 1: Open a new google tab Step 2: Go to the left hand upper corn…
Look below the covers at a subform control , and the form that is inside it. Explore properties and see how easy it is to aggregate, get statistics, and synchronize results for your data. A Microsoft Access subform is used to show relevant calcul…
Suggested Courses

927 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question