Contains on two values? [duplicate] - c#

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.
}

Related

Is there ToSortedDictionary in Linq? [duplicate]

This question already has answers here:
Building a sorted dictionary using ToDictionary
(3 answers)
Closed 5 years ago.
I am refactoring a code like this:
var result = new SortedDictionary<int, string>();
foreach (var item in foo)
{
result[item.id] = item.name;
}
foreach (var item in bar)
{
result[item.id] = item.name;
}
return result;
I would like to write:
return foo.Concat(bar).ToSortedDictionary(i => i.id, i => i.name);
but I did not find it in Linq?
First solution is to prepare Dictionaryand use as an argument to create a SortedDictionary:
return new SortedDictionary<T1, T2>(foo.Concat(bar).ToDictionary())
Another option is to write an extension method like this:
public static SortedDictionary<K, V> ToSortedDictionary<K,V>(this Dictionary<K, V> existing)
{
return new SortedDictionary<K, V>(existing);
}
You can use return new SortedDictionary<T1, T2>(foo.Concat(bar).ToDictionary()); or you can write your own extension method.
As to why it doesn't exist, there's plenty of similar methods that don't exist- the basics are provided and whatever else you need you can easily make yourself.

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.

Assinging a sequential "row number" in linq output [duplicate]

This question already has answers here:
LINQ: Add RowNumber Column
(9 answers)
Closed 6 years ago.
I would like to access the row number in linq query.
There are many articles on the web stating how to do this but there is a catch:
I want to resolve the enumeration "later" and I want it to assign the same ID every time.
For this reason methods such as this do not work:
public IEnumerable<MyClass> GetThings(List<object> lst)
{
int ID=0;
return from i in lst
select new MyClass(ID++, i);
}
public class MyClass
{
public MyClass(int ID, object Stuff)
{ ... }
}
...
var x = GetThings(SomeList);
(fails because each time you resolve x by iterating each item gets a different id)
Actually you can use the Select overload that pass the index too, something like this:
lst.Select((o, i) => new MyClass(i, o));
Turns out the solution to this is quite simple - grab the row number of the source collection, not the output collection.
Obviously this only works if you are not filtering etc. and the number of items in your output collection is the same as the input collection. Unless you're ok with gaps and/or duplicates
i.e.
public IEnumerable<MyClass> GetThings(List<object> lst)
{
int ID=0;
return from i in lst.Select((item,id)=>new {Item=item, ID=id})
select new MyClass(i.ID, i.Item);
}
public class MyClass
{
public MyClass(int ID, object Stuff)
{ ... }
}
...
var x = GetThings(SomeList);
now the ID's of each item in x is the same every time you iterate it

Emptying a List<string> [duplicate]

This question already has answers here:
How to empty a list in C#?
(7 answers)
Closed 8 years ago.
This has probably been asked somewhere, but I was unable to find it.
I have a List of strings like this :
public static List<string> AnimalsL = new List<string>();
public static void ListAnimals()
{
AnimalsL.Add("Animal one");
AnimalsL.Add("Animal two");
}
public static void ReturnAnimals()
{
string[] Animals = AnimalsL.ToArray();
if(AnimalsL != null)
{
for(int Index = 0; Index < Animals.Length; Index++)
{
System.Windows.Forms.MessageBox.Show(Animals[Index].ToString());
}
}
}
[b] Above is working code [/b]
So, as the title says, my real question is : How to completely empty a List of strings ?
For instance, I could want to store the animal names IF the animals type is snake, or dog, and I wouldn't want them crossing into the same category, or if I want to ensure the list is empty before adding to it, or clear it once I've used my methods on the animal.
I was thinking of declaring Animals[] = string.Empty, but this wouldn't actually clear the list ..
There are two ways to do this.
1.
AnimalsL.Clear(); // clears all the items in the list
2.
AnimalsL = new List<string>(); // assigns a new instance
Actually, creating a new instance is faster than calling the Clear method, though if you want to keep the reference to that object, then calling Clear is better.
Here is a benchmark for Clear() vs new List Link
Use List<T>.Clear() method to remove all entries from a list instance.

Merge List<T> objects [duplicate]

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);

Categories