I know that this can be rewritten using a lambda expression. But I cant seem to figure it out. does anyone have an opinion on how it should be written using a lambda.
foreach (var _systemItem in _systemData)
{
foreach (var _institutionItem in _institutionData)
{
if (_systemItem.LookupValue == _institutionItem.OriginalSystemLookupValue)
{
_values.Add(new LookupValue()
{
DisplayText = _institutionItem.LookupText,
Value = _institutionItem.LookupValue
});
}
else
{
_values.Add(new LookupValue()
{
DisplayText = _systemItem.LookupText,
Value = _systemItem.LookupValue
});
}
}
}
Like this:
values.AddRange(from s in _systemData
from i in institutionData
select s.LookupValue == i.OriginalSystemLookupValue ?
new LookupValue {
DisplayText = _institutionItem.LookupText,
Value = _institutionItem.LookupValue
}
: new LookupValue {
DisplayText = _systemItem.LookupText,
Value = _systemItem.LookupValue
}
);
Is _values a List<LookupValue> which is empty to start with? If so, that look might look like this:
_values = (from x in _systemData
from y in _institutionData
let item = x.LookupValue == y.OriginalSystemLookupValue ? x : y
select new LookupValue { DisplayText = item.LookupText,
Value = item.LookupValue })
.ToList();
That assumes that _systemItem and _institutionItem are the same type. If they're unrelated types, you might want to give them a common interface that defines LookupText and LookupValue (or even a ToLookupValue method) and then cast one of the operands in the conditional operator to the interface. For example:
_values = (from x in _systemData
from y in _institutionData
let item = x.LookupValue == y.OriginalSystemLookupValue
? (ILookupSource) x : y
select item.ToLookupValue())
.ToList();
Sure, I have an opinion. I'd write it like this:
var pairs = _systemData.SelectMany(s =>
_institutionData.Select(i => new { System = s, Institution = i }));
_values.AddRange(pairs.Select(x =>
{
bool match = x.System.LookupValue == x.Insitution.OriginalSystemLookupValue;
return match ? new LookupValue(x.Institution) : new LookupValue(x.System);
}));
And move the object initializers for LookupValue into real constructors that take an Institution or System.
Related
I have this method with a linq statement below. I'm not a fan of multiple if statement and I'm trying to find what is the best way to not have these if statement and have a private method.
My field values is being set as such:
var fieldValues = await GetFields // then it's being passed to my method.
public static AppraisalContactBorrower BuildCoBorrower(List<LoanFieldValue> fieldValues) {
var coborrower = new AppraisalContactBorrower();
if (fieldValues.Exists(f => f.FieldId == "CX.OS.AO.COBORRNAME")) {
coborrower.Name = fieldValues.First(v => v.FieldId == "CX.OS.AO.COBORRNAME").Value;
}
if (fieldValues.Exists(f => f.FieldId == "CX.OS.AO.BORRCONTACTZIP")) {
borrower.Zip = fieldValues.First(v => v.FieldId == "CX.OS.AO.BORRCONTACTZIP").Value;
}
if (fieldValues.Exists(f => f.FieldId == "CX.OS.AO.BORRCONTACTZIP")) {
borrower.Zip = fieldValues.First(v => v.FieldId == "CX.OS.AO.BORRCONTACTZIP").Value;
}
What I'm trying to do is instead of this:
coborrower.Name = fieldValues.First(v => v.FieldId == "CX.OS.AO.COBORRNAME").Value;
Is having something similar to this.
if (fieldValues.Exists(f => f.FieldId == "CX.OS.AO.BORRCONTACTZIP")) {
coborrower.Name = SETVALUE("CX.OS.AO.BORRCONTACTZIP")}
First, try using Enumerable.ToDictionary to have the field values grouped by FieldId, then use IDictionary.TryGetValue to get the existing values:
public static AppraisalContactBorrower BuildCoBorrower(List<LoanFieldValue> fieldValues) {
var groupedFieldValues = fieldValues.ToDictionary(f => f.FieldId)
var coborrower = new AppraisalContactBorrower();
if (groupedFieldValues.TryGetValue("CX.OS.AO.COBORRNAME", out var name)) {
coborrower.Name = name.Value;
}
if (groupedFieldValues.TryGetValue("CX.OS.AO.BORRCONTACTZIP", out var zip)) {
borrower.Zip = zip.Value;
}
}
Using Dictionary makes it faster to check the appropriate field existence as it is O(1) and with TryGetValue you combine two operations into one (existence check + obtaining the value).
Your two last statements are almost identitical. The equivalent of :
if (groupedFieldValues.TryGetValue("CX.OS.AO.COBORRNAME", out var name)) {
coborrower.Name = name.Value;
}
is:
coborrower.Name = fieldValues.FirstOrDefault(v => v.FieldId == "CX.OS.AO.COBORRNAME")
?? coborrower.Name;
In the original code, coborrower.Name is not updated if the field doesn't exist in the list.
I've tried to search SO for solutions and questions that could be similar to my case.
I got 2 collections of objects:
public class BRSDocument
{
public string IdentifierValue { get; set;}
}
public class BRSMetadata
{
public string Value { get; set;}
}
I fill the list from my datalayer:
List<BRSDocument> colBRSDocuments = Common.Instance.GetBRSDocuments();
List<BRSMetadata> colBRSMetadata = Common.Instance.GetMessageBRSMetadata();
I now want to find that one object in colBRSDocuments where x.IdentifierValue is equal to the one object in colBRSMetadata y.Value. I just need to find the BRSDocument that matches a value from the BRSMetadata objects.
I used a ordinary foreach loop and a simple linq search to find the data and break when the value is found. I'm wondering if the search can be done completely with linq?
foreach (var item in colBRSMetadata)
{
BRSDocument res = colBRSDocuments.FirstOrDefault(x => x.IdentifierValue == item.Value);
if (res != null)
{
//Do work
break;
}
}
Hope that some of you guys can push me in the right direction...
Why not do a join?
var docs = from d in colBRSDocuments
join m in colBRSMetadata on d.IdentiferValue equals m.Value
select d;
If there's only meant to be one then you can do:
var doc = docs.Single(); // will throw if there is not exactly one element
If you want to return both objects, then you can do the following:
var docsAndData = from d in colBRSDocuments
join m in colBRSMetadata on d.IdentiferValue equals m.Value
select new
{
Doc = d,
Data = m
};
then you can access like:
foreach (var dd in docsAndData)
{
// dd.Doc
// dd.Data
}
Use Linq ?
Something like this should do the job :
foreach (var res in colBRSMetadata.Select(item => colBRSDocuments.FirstOrDefault(x => x.IdentifierValue == item.Value)).Where(res => res != null))
{
//Do work
break;
}
If you are just interested by the first item, then the code would be :
var brsDocument = colBRSMetadata.Select(item => colBRSDocuments.FirstOrDefault(x => x.IdentifierValue == item.Value)).FirstOrDefault(res => res != null);
if (brsDocument != null)
//Do Stuff
I have this code :
(simple enum which has values for a,b,c ...[0,1,2] , and i want to show for each looped number - its corrosponding enum in a final list).
public enum ENM
{
a,b,c
}
void Main()
{
var e = Enumerable.Range(0,3).Select(myCounter=>new {
final=((Func<int,ENM>)delegate (int i)
{
return (ENM)i;
})(myCounter)
}).ToList();
this is fine and working.
Is there any solution without writing delegate(int i) {...}?
p.s. of course I can just write (ENM)i but the question is for learning
how to write ( in different ways ) the auto-executed methods.
Why not
Enumerable.Range(0,3).Select(c=>(ENM)c).ToList()
or am I missing some reason for the over complexity?
var e = Enumerable.Range(0, 3).Select(myCounter => new
{
final = ((Func<int, ENM>)(
i=>{
return (ENM)i;
/* More code could be here */
}))(myCounter)
}).ToList();
is about as tight as you will get if you want the same mess :)
var e = Enum.GetNames(typeof(ENM)).Select((e, i) => new { final = e, index = i }).ToList();
OR
var EnumNames = Enum.GetNames(typeof(ENM));
var EnumValues = Enum.GetValues(typeof(ENM)).Cast<ENM>().Select(e => (int)e);
var result = EnumNames.Zip(EnumValues, (n, v) => new { final = n, index = v });
There's a specific method in System.Enum for doing exactly this:
var arr = Enum.GetValues(typeof(ENM));
To get it into a List<ENM>:
var lst = arr.Cast<ENM>().ToList();
I have class like:
class SortNode
{
public Int32 m_valRating = 0;
public SortNode(Int32 valRating)
{
this.m_valRating = valRating;
}
}
and some list refSortNodeList:
List<SortNode> refSortNodeList = new List<SortNode>();
Random refRandom = new Random();
for (int i = 0; i < 100; ++i)
{
refSortNodeList.Add(new SortNode(refRandom.Next(-10, 30)));
}
foreach (var varSortNode in refSortNodeList)
{
Console.WriteLine("SortNode rating is {0}", varSortNode.m_valRating);
}
How to sort easily my refSortNodeList by m_valRating field? Or maybe I need to use some another List class?
list.Sort((x,y) =>
x.m_valRating.CompareTo(y.m_valRating));
In-place:
refSortNodeList.Sort(
(x, y) =>
x == null ? (y == null ? 0 : -1)
: (y == null ? 1 : x.m_valRating.CompareTo(y.m_valRating))
);
Creating a new enumeration:
var newEnum = refSortNodeList.OrderBy(x => x.m_valRating);
Creating a new list:
var newList = refSortNodeList.OrderBy(x => x.m_valRating).ToList();
In-place is fastest and most memory efficient, but no good if you want to also retain the old list.
The next is faster than the last and gives results as they go, but you have to re-do the sort to use it again, in which case the third is the one to go for.
Use Linq order by.
var mySortedList = refSortNodeList.OrderBy(x => x.m_valRating);
Here is a real live example where I am pulling a list from a database but it is exactly the same concept.
vendorProducts = (from vp in db.COMPANIES_VND_PRODUCTS
join p in db.CT_CT_INV_CLASSES on vp.CLASS_ID equals p.CLASS_ID
join m in db.CT_CT_MODALITY_CODES on vp.MODALITY_ID equals m.MODALITY_ID
where vp.COMPANY_ID == companyId
select new ProductTypeModality
{
Active = p.ACTIVE.Equals("Y") ? true : false,
BioMedImaging = p.BIOMED_IMAGING,
Code = p.CLASS_CODE,
Description = p.DESCRIPTION,
Id = p.CLASS_ID,
PricingMargin = p.PRICING_MARGIN,
ModalityCode = m.MODALITY_CODE,
ModalityId = m.MODALITY_ID,
VendorId = companyId
}).OrderBy(x => x.Code).ToList<ProductTypeModality>();
Implement IComparable<T>
You can use Linq for basic sorts:
refSortNodeList.OrderBy(n => n.m_valRating);
If you need more complex sorting your will need to implement IComparable to use the built in sorting.
Try this:
refSortNodeList.Sort(new delgate(SortNode x, SortNode y)
{
return x.CompareTo(y);
}
);
It's easy using linq:
var newlist = refSortNodeList.sort( n => n.m_valRating );
List<SortNode> refSortNodeList = new List<SortNode> ();
Random refRandom = new Random ();
for (int i = 0; i < 100; ++i) {
refSortNodeList.Add (new SortNode (refRandom.Next (-10, 30)));
}
// Use this (Linq) if you're using .NET 3.5 or above.
var sortedList = refSortNodeList.OrderBy (node => node.m_valRating);
foreach (var varSortNode in sortedList) {
Console.WriteLine ("SortNode rating is {0}", varSortNode.m_valRating);
}
// Use this otherwise (e.g. .NET 2.0)
refSortNodeList.Sort (
delegate (SortNode n1, SortNode n2) {
return n1.m_valRating.CompareTo (n2.m_valRating);
}
);
foreach (var varSortNode in refSortNodeList) {
Console.WriteLine ("SortNode rating is {0}", varSortNode.m_valRating);
}
part of the code:
Dictionary<Calculation, List<PropertyValue>> result = new Dictionary<Calculation, List<PropertyValue>>();
while (reader != null && reader.Read()) //it loops about 60000, and it will be bigger
{
#region create calc and propvalue variables
//...
#endregion
//this FirstOrDefault needs a lot of time
tmpElementOfResult = result.Keys.FirstOrDefault(r => r.InnerID == calc.InnerID);
if (tmpElementOfResult == null)
{
result.Add(calc, new List<PropertyValue> { propValue });
}
else
{
result[tmpElementOfResult].Add(propValue);
}
}
Could you give me some idea how to make it faster, because now it's approximately 25 sec :( ?
It sounds like you should have a dictionary from the type of calc.InnerID, instead of a Dictionary<Calc, ...>. That way you can do the lookup far more quickly. Do you actually need to store the Calc itself at all, or are you only interested in the ID?
For example:
Dictionary<Guid, List<PropertyValue>> result =
new Dictionary<Guid, List<PropertyValue>>();
while (reader.Read())
{
// Work out calc
List<PropertyValue> list;
if (!result.TryGetValue(calc.InnerID, out list))
{
list = new List<PropertyValue>();
result[calc.InnerID] = list;
}
list.Add(propValue);
}
Alternatively, if you can convert the reader to an IEnumerable<Calc> you could use:
Lookup<Guid, PropertyValue> result = items.ToLookup(x => x.InnerID,
// Or however you get it...
x => x.PropertyValue);
EDIT: It sounds like two Calc values should be deemed equal if they have the same InnerID, right? So override Equals and GetHashCode within Calc to refer to the InnerID. Then you can just use:
Lookup<Calc, PropertyValue> result = items.ToLookup(x => x,
// Or however you get it...
x => x.PropertyValue);
... or you can use code like the first snippet, but with a Dictionary<Calc, ...>:
Dictionary<Calc, List<PropertyValue>> result =
new Dictionary<Calc, List<PropertyValue>>();
while (reader.Read())
{
// Work out calc
List<PropertyValue> list;
if (!result.TryGetValue(calc, out list))
{
list = new List<PropertyValue>();
result[calc] = list;
}
list.Add(propValue);
}
instead of
tmpElementOfResult = result.Keys.FirstOrDefault(r => r.InnerID == calc.InnerID);
use
result.ContainsKey(calc.InnerId);
to check if a key is present.
Is it possible to do something like this:
lookUpForResult = result.ToLookup(x => x.Key.InnerID, x => x.Value);
if (lookUpForResult.Contains(calc.InnerID))
{
result.Add(calc, new List<PropertyValue> { propValue });
}
else
{
(lookUpForResult[calc.InnerID]).Add(propValue);
}