Merge List<T> objects [duplicate] - c#

This question already has answers here:
Merge two (or more) lists into one, in C# .NET
(14 answers)
Create a list from two object lists with linq
(8 answers)
Closed 9 years ago.
I have an asp.net application where I have 4 List collection objects
List<string> sTransID = new List<string>();
List<string> sOriginID = new List<string>();
List<string> sDestID = new List<string>();
List<string> sCourierID = new List<string>();
These objects are populated at different sections of the application (inside a class, or an aspx code behind etc). The page performance is significantly slow when List elements size increase.
What would be the fastest way to loop through these objects when reading their values (in order to avoid having to loop through 4 objects) ? Can I merge these objects into a parent List object and loop through the parent?
Update:
By merge, I mean something like:
var Parent = List<sTransID>, List<sOriginID>, List<sDestID>, List<sCourierID>
var GetLocation = Parent[0]; // will return TransID[0], Origin[0], DestID[0], CourierID[0]

I have an Extension method that merges dictionaries. It might be of some help if you modify it for Lists.
public static class DictionaryExtensions
{
public static T MergeLeft<T, K, V>(this T me, params IDictionary<K, V>[] others)
where T : IDictionary<K, V>, new()
{
var newMap = new T();
foreach (var p in (new List<IDictionary<K, V>> { me }).Concat(others).SelectMany(src => src))
{
newMap[p.Key] = p.Value;
}
return newMap;
}
}
used as follows:
var mergedDictionary = new Dictionary<string, string>().MergeLeft(dic1, dic2, dic3);

One way would be to just concat the lists together before looping:
var itemsToLoop = sTransID.Concat(sOriginID).Concat(sDestID).Concat(sCourierID);

Related

Updating items in an IEnumerable [duplicate]

This question already has answers here:
Item from IEnumerable changed inside foreach, but change not saved to collection
(1 answer)
C# failing to set property inside IEnumerable
(5 answers)
Closed 3 years ago.
I have this code:
class Foo
{
public string A { get; set; }
}
class Program
{
static void Main(string[] args)
{
var strings = new List<string> { "foo", "foo" };
var list = strings.Select(x => new Foo { A = x });
foreach (var item in list)
{
item.A = "bar";
}
foreach (var item in list)
{
Console.WriteLine(item.A);
}
}
}
Which prints:
foo
foo
What exactly happens when you set item.A = "bar" ?
After the first foreach loop finishes, does the list var really contain the same two Foo objects with "bar" as the new string?
If so, how could you access these new values?
I understand that when the 2nd foreach loop runs, it is enumerating the collection of strings which is why you get two print outs of "foo", but I'm just confused as to what happens when item.A = "bar" is run, and if you are never able to access that new value, why does the compiler allow you to modify it?
What's happening here is that you are creating an enumerable list which you are enumerating multiple times.
Each time you enumerate list, the enumeration processes the elements of the strings list calling new Foo { A = x } for each element to create the elements of the resulting sequence.
That means the the Foo objects created by the first foreach enumeration are NOT the same as the ones created by the second foreach enumeration. New ones are created for each enumeration.
This is the reason that Resharper warns about "possible multiple enumeration".
To avoid this, you would use var list = strings.Select(x => new Foo { A = x }).ToList(); to enumerate the sequence just once and store the results in an actual List<T>.
The problem is that you haven't called ToList method to materialize your LINQ query. When you call ToList as below:
var list = strings.Select(x => new Foo { A = x })
.ToList();
an in-memory collection of Foo objects would be created, whose property value A would have the value x. Essentially two new objects of type Foo would be created with the value of A to be "foo". Then you can loop through this list and modify the property value.
Please look at this fiddle
You are right that if will not going to be chnaged, then why compiler allow. but if you want to print without updating actual item in this scenario above code will helpful.
One thing you should know that, you can not modified the item of IEnumerable object.
you have to use List();
var strings = new List<string> { "foo", "foo" };
var list = strings.Select(x => new Foo { A = x }).ToList();
foreach (var item in list)
{
item.A = "bar";
}
foreach (var item in list)
{
Console.WriteLine(item.A);
}

C# copy List<dynamic> without reference [duplicate]

This question already has answers here:
In C# if an object in a list is added to another list, does changing the object in the second list change the same object in the first list?
(2 answers)
How to make correct clone of the List<MyObject>? [duplicate]
(3 answers)
Closed 5 years ago.
I have a List<dynamic> that I need to copy and then, based on a condition of the row of the list I need to modify a field of that row and add it to the second list.
This a sample of the code:
//list1 is a `List<dynamic>` that I get from a query using Dapper. I guess it is an ExpandoObject list
var list2 = new List<dynamic>(list1);
foreach (var obj in list2)
{
if (obj.condition == 1)
{
var newObj = obj;
newObj.description = "new row";
list2.Add(newObj);
}
}
My problem is that in both my list the obj in the list is updated with the string 'new row'.
It seems like every time I change newObj both lists are updated.
I also tried to create my list2 this way but I have the same problem:
var list2 = new BindingList<dynamic>(list1);
EDIT:
I looked at the other questions but in my case, I only have a dynamic List. Is it possible to get the result I want without having to create a Class and implement ICloneable?
Try
var list2 = list1.Select(x => x);

Extension method on Item in List within another List [duplicate]

This question already has answers here:
Flatten List in LINQ
(5 answers)
Closed 6 years ago.
I'm trying to perform an run an extension method on every item within a List<> that is inside another List<> to return collection of a given type (returned by the extension method).
I initially tried (and failed) to do this using linq, but I have the following:
var dataset = GetReportDataset(org);
var reportData = new List<InterventionAndNeetRiskReportLineModel>();
foreach (var record in dataset)
{
foreach (var inter in record.InterventionHistory)
{
reportData.Add(inter.ToInterventionAndNeetRiskReportLineModel());
}
}
return _reportWriter.ReportCsvStream(reportData);
So my question is, how can I project the result of my extension method for each item in the child collection using linq?
UPDATE ToInterventionAndNeetRiskReportLineModel() extension method
public static InterventionAndNeetRiskReportLineModel ToInterventionAndNeetRiskReportLineModel(this InterventionHistory intervention)
{
return new InterventionAndNeetRiskReportLineModel()
{
Beneficiary = intervention.Person.Beneficiary,
CourseTitle = intervention.CourseTitle,
CaseNotes = intervention.CaseNotes,
EndDate = intervention.EndDate?.ToString(),
StartDate = intervention.StartDate.ToString(),
ParticipantId = intervention.Person.ParticipantId,
FirstEit = intervention.Person.EitScores.GetFirstEitReading().ToString(),
LastEit = intervention.Person.EitScores.GetLastEitReading().ToString(),
FirstLpt = intervention.Person.LptScores.GetFirstLptReading().ToString(),
LastLpt = intervention.Person.LptScores.GetLastLptReading().ToString(),
Gender = intervention.Person.Equalitites.Gender,
HoursAttended = intervention.NoOfHours.ToString(),
LanguageOfDelivery = intervention.DeliveryLanguage,
Providername = intervention.ProviderName,
QanCode = intervention.QanCode,
SchoolCollegeName = intervention.ProviderName
};
}
I'm not completely sure which part of the question code you want to separate into an extension method. Also, don't be to focused on the extension method part, its nothing different from other functions, as far as the writing is concerned.
You can use SelectMany in order to get a flat list of InterventionHistory objects and Select in order to convert to InterventionAndNeetRiskReportLineModel and ToList for the final result as list instead of IEnumerable<T> if you really need that.
var reportData = GetReportDataset(org)
.SelectMany(r => r.InterventionHistory)
.Select(i => i.ToInterventionAndNeetRiskReportLineModel())
.ToList();
So, maybe you want an extension method like
public static IEnumerable<InterventionAndNeetRiskReportLineModel> ToInterventionRiskReports(this IEnumerable<ReportDataset> _self)
return _self
.SelectMany(r => r.InterventionHistory)
.Select(i => i.ToInterventionAndNeetRiskReportLineModel());
}
And use it as
var reportData = GetReportDataset(org).ToInterventionRiskReports().ToList();
... as I said, its not completely clear, which part you want to refactor into an extension method.

Contains on two values? [duplicate]

This question already has answers here:
Does .NET have a way to check if List a contains all items in List b?
(5 answers)
Closed 7 years ago.
I've got a List properties that must contain both pivot1 and pivot2.
How can I make Contains work with BOTH values?
List<string> properties = line.Split('|').ToList();
string pivot1 = "value1";
string pivot2 = "value2";
if(properties.Contains(pivot1) && properties.Contains(pivot2))
{
// do stuff.
}
Aside from writing an extension/helper method, you can use LINQ to shorten it a bit:
if (new[] { pivot1, pivot2 }.All(properties.Contains))
{
}
Although this is somewhat less readable I'd argue.
I personally like maintaining a Utility class to build up my own helpful framework to compliment .NET. I'd do something like:
public static bool ContainsAll<T>(this IEnumerable<T> list, params T[] items)
{
foreach(var item in items)
{
if (!list.Contains(item))
return false;
}
return true;
}
then you can use:
if(properties.ContainsAll(pivot1, pivot2))
{
}
You are not initializing properties or adding anything to it.
List<string> properties = new List<string>();
properties.Add("value1");
properties.Add("value2");
string pivot1 = "value1";
string pivot2 = "value2";
if(properties.Contains(pivot1) && properties.Contains(pivot2))
{
// do stuff.
}

Creating an Array Vs List [duplicate]

This question already has answers here:
Array versus List<T>: When to use which?
(16 answers)
Closed 7 years ago.
In the below code,
is it more efficient (in terms of memory and time) to create a List<string> directly, rather than creating a string[] and calling ToList() on it before passing it to SomeMethod()?
If you create the string[] and call ToList(), would it create a List<string> object, as well as already having the string[]?
The reason I ask is that I have seen code where they are creating a string[] and calling ToList() before passing it as an argument to a method with a List<string> parameter, and I wasn't sure if there was any particular reason for that.
class Program
{
static void Main(string[] args)
{
var array = new string[] { "str1", "str2" };
SomeMethod(array.ToList());
var list = new List<string> { "str1", "str2" };
SomeMethod(list);
}
static void SomeMethod(List<string> list)
{
//do stuff
}
}
Every .ToList() and .ToArray() creates new objects, allocates memory, copies values. So, try to minimize such operations
Use more common types: IEnumerable, ICollection. Because both list and array are suitable for IEnumerable, for example:
class Program
{
static void Main(string[] args)
{
var array = new string[] { "str1", "str2" };
SomeMethod(array);
var list = new List<string> { "str1", "str2" };
SomeMethod(list);
}
static void SomeMethod(IEnumerable<string> list)
{
//do stuff
}
}
Reference.
ToArray Method of List:
public T[] ToArray()
{
T[] objArray = new T[this._size];
Array.Copy((Array) this._items, 0, (Array) objArray, 0, this._size);
return objArray;
}
You can see, it copies data.
ToList method:
public static List<TSource> ToList<TSource>(this IEnumerable<TSource> source)
{
if (source == null)
throw Error.ArgumentNull("source");
return new List<TSource>(source);
}
You can see, it creates new list object. And constructor List(IEnumerable<T> collection) copies data.
I'd expect it to be more memory efficient to go straight to the List, but time would depend on inner workings. ToList would probably consist of creating a list and then moving the data over from the array, however, which seems inefficient in terms of time too.
Try running some tests doing each method 100000 or so times, and seeing the amount of time this takes in each test.

Categories