Splitting lists into chunks.

Whilst writing a process to upload instore purchases to Facebook using their offline conversion API I discovered that their API only accepts a maximum of 2,100 events in any one API call. As I already ahd a nice list of events I had a look around and managed to find this extension method for lists to break them into chunks of a specified size.

	
public static class ListExtensions
{
	public static List<List<T>> ChunkBy<T>(this List<T> source, int chunkSize)
	{
		return source
			.Select((x, i) => new { Index = i, Value = x })
			.GroupBy(x => x.Index / chunkSize)
			.Select(x => x.Select(v => v.Value).ToList())
			.ToList();
	}
}
	

I can then call loop through the resulting list of lists like so.

	
// Get transactions
List<Data> data = Common.GetData();

// Split into chunks of 2100 as this is maximum FB can process
List<List<Data>> dataChunks = data.ChunkBy(2100);

foreach (List<Data> dataChunk in dataChunks)
{
	string dataString = JsonConvert.SerializeObject(dataChunk, Formatting.None, new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore });

	// Upload to Facebook
	string url = "https://graph.facebook.com/v2.10/" + ConfigurationManager.AppSettings["OfflineConversionDatasetId"] + "/events";

	using (HttpClient client = new HttpClient())
	{
		List<KeyValuePair<string, string>> formFields = new List<KeyValuePair<string, string>>();

		string formString = "access_token=" + ConfigurationManager.AppSettings["AccessToken"];
		formString += "&upload_tag=" + ConfigurationManager.AppSettings["UploadTag"];
		formString += "&data=" + dataString;

		StringContent stringContent = new StringContent(formString, Encoding.UTF8, "application/json");

		HttpResponseMessage response = client.PostAsync(url, stringContent).Result;

		response.EnsureSuccessStatusCode();
	}
}
	

Leave a Reply

Your email address will not be published. Required fields are marked *