Linq Lambda Expression to check null or empty - c#

Im new to Linq and Lambda expressions and I wanted to change this piece of code:
if (string.IsNullOrEmpty(model.PictureUrl1) && string.IsNullOrEmpty(model.Picture2Url) &&
string.IsNullOrEmpty(model.Picture3Url) && string.IsNullOrEmpty(model.Picture4Url) &&
string.IsNullOrEmpty(model.Picture5Url) && string.IsNullOrEmpty(model.Picture6Url))
return Content("");
Now I refactored that model to have an object with those properties and a list of said objects:
public class PublicInfoModelItem
{
public string PictureUrl { get; set; }
public string Text { get; set; }
public string Link { get; set; }
}
And the list:
public List<PublicInfoModelItem> ListOfImages = new List<PublicInfoModelItem>();
Model:
public class PublicInfoModel
{
public List<PublicInfoModelItem> ListOfImages = new List<PublicInfoModelItem>();
public string Container { get; set; }
public int TemplateId { get; set; }
public PublicInfoModelItem InfoModelItem { get; set; }
}
And I was thinking a Lambda expression, something like:
var result = model.ListOfImages.Where(x => string.IsNullOrEmpty(x.PictureUrl)).ToList();
if (result == null)
{
return Content("");
}
I dont know if the above expression is correct or it could be improved.

I think you want to use Any:
if (!model.ListOfImages.Any(x => string.IsNullOrEmpty(x.PictureUrl)))
{
return Content("");
}

Just to append Brett`s solution:
if (!model.ListOfImages.Any(x => string.IsNullOrEmpty(x.PictureUrl)))
{
return Content("");
}
Might be what you were looking for. But it is almost the same as:
if(model.ListOfImages.All(x=> !string.IsNullOrEmpty(x.PictureUrl)))
{
return Content("");
}
the only difference here is: Any will return on the first item that gets evaluated to true and All on the first which gets to false for the predicate. But since All's predicate gets negated, it will occur at the same element in the list and will have the same result.
But All comes in handy when you want some more checking, for example:
if(model.ListOfImages.All(x=> !string.IsNullOrEmpty(x.PictureUrl) && x.PictureUrl.EndsWith(".jpg")))
{
return Content("");
}

You want to find if a null/empty value exists. So another option would be to use Exists():
if(model.ListOfImages.Exists(image => string.IsNullOrEmpty(x.PictureUrl)))
{
return Content("");
}

Yes you can do that. I apply as follows:
var accionistas = repositorio.FindEntitySet<TBL_Accionista>(p => p.Estatus.Equals(1)).Select(a => new { a.Id_Accionista, Nombre = a.Apellido_Paterno + " " + a.Apellido_Materno + " " + a.Primer_Nombre, RazonSocial = String.IsNullOrEmpty(a.Razon_Social)?string.Empty:a.Razon_Social, a.RFC });

You can try something like this to filter out some value:
var result = ListOfImages.Any(x => (!string.IsNullOrEmpty(x.PictureUrl)) && (x.PictureUrl.Contains("text-to-filter")));

Related

Linq query for the Multi list in singe out put

i have table looks like below
ID | Reason | PrID
-----------------
1 abc null
2 dhe null
3 aerc 1
4 dwes 2
5 adfje 1
i have class
public class Reason
{
public int Id { get; set; }
public string Reson{ get; set; }
public List<SecondryReason> SecReason{ get; set; }
public int? PrimaryId { get; set; }
}
public class SecondryReason
{
public int Id { get; set; }
public string Reason { get; set; }
public int PrimaryReasonId { get; set; }
}
I want this to be displayed in hierarchy level
if the prid is Null need to treat this as the parent remaining all child
i am trying Linq and unable to achieve this
Suggest me how to do this in an easy way in linq
So: You have a list/enumerable of type , whereof the SecReason List property is null. Then, using linq you want a list, were the only the "root" reasons remain, but the Sub-reasons got put in the lists, but as type SecondaryReason?
If so, I found this way to do it (linq and foreach):
static IEnumerable<Reason> GetReasonsGrouped(List<Reason> reasons)
{
var result = reasons.Where(x => x.PrimaryId == null);
foreach (var item in result)
{
item.SecReason = reasons.Where(x => x.PrimaryId == item.Id)
.Select(x => new SecondryReason()
{ Id = x.Id,
ReasonName = x.ReasonName,
PrimaryReasonId = item.Id
})
.ToList();
}
return result;
}
Or just linq, but harder to read:
var result = reasons.Where(x => x.PrimaryId == null)
.Select(x =>
{
x.SecReason = reasons.Where(r => x.PrimaryId == x.Id)
.Select(r => new SecondryReason()
{
Id = r.Id,
ReasonName = x.ReasonName,
PrimaryReasonId = x.Id
})
.ToList();
return x;
});
Not sure if linq will be the best solution, here is my proposed changes and method to get an Hierarchy type:
public class Reason
{
public int Id { get; set; }
public string Reson { get; set; }
public List<Reason> SecReason { get; set; }
public int? PrimaryId { get; set; }
//Adds child to this reason object or any of its children/grandchildren/... identified by primaryId
public bool addChild(int primaryId, Reason newChildNode)
{
if (Id.Equals(primaryId))
{
addChild(newChildNode);
return true;
}
else
{
if (SecReason != null)
{
foreach (Reason child in SecReason)
{
if (child.addChild(primaryId, newChildNode))
return true;
}
}
}
return false;
}
public void addChild(Reason child)
{
if (SecReason == null) SecReason = new List<Reason>();
SecReason.Add(child);
}
}
private List<Reason> GetReasonsHierarchy(List<Reason> reasons)
{
List<Reason> reasonsHierarchy = new List<Reason>();
foreach (Reason r in reasons)
{
bool parentFound = false;
if (r.PrimaryId != null)
{
foreach (Reason parent in reasonsHierarchy)
{
parentFound = parent.addChild(r.PrimaryId.Value, r);
if (parentFound) break;
}
}
if (!parentFound) reasonsHierarchy.Add(r);
}
return reasonsHierarchy;
}

How to instantiate lists of same type within a complex object ?

It's a tricky situation I ran into . I know it is a simple one but something i guess I am missing.
There is complex type object ..
public class GroupMembershipValidationOutput
{
public ListGroupMembershipUploadInput GroupMembershipInvalidList { get; set; }
public ListGroupMembershipUploadInput GroupMembershipValidList { get; set; }
...................... // other defs
}
The ListGroupMembershipUploadInput looks like
public class ListGroupMembershipUploadInput
{
public List<GroupMembershipUploadInput> GroupMembershipUploadInputList { get; set; }
}
Now there is a parent list of objects(that is also of the same type) form where I am parsing the valid and the invalid lists respectively.
GroupMembershipValidationOutput gmvo = new GroupMembershipValidationOutput();
ListGroupMembershipUploadInput lgl = new ListGroupMembershipUploadInput();
if (gmvo._invalidChapterCodes.Count != 0 || gmvo._invalidGroupCodes.Count != 0 || gmvo._invalidMasterIds.Count != 0)
{
lgl.GroupMembershipUploadInputList = new List<GroupMembershipUploadInput>();
var result = mainCollection.GroupMembershipUploadInputList
.Where(x => gmvo._invalidMasterIds.Select(y => y).Contains(x.cnst_mstr_id) ||
gmvo._invalidChapterCodes.Select(y => y).Contains(x.chpt_cd) ||
gmvo._invalidGroupCodes.Select(y => y).Contains(x.grp_cd)).ToList();
if (result.Count > 0) //Means there are some invalid items
{
lgl.GroupMembershipUploadInputList = result; //Construct the invalid listfrom result
gmvo.GroupMembershipInvalidList = lgl;
......... // How to construct the valid list
}
I tried
gmvo.GroupMembershipValidList = new ListGroupMembershipUploadInput();
but it assigns null to the GroupMembershipValidList .. it does not make the count 0.
How to fix it ? Or is it the intended one ?

How can I filter a collection so I get only the rows where the value of a fields is not null?

I have a call to GetData() that returns a collection of TQ:
IList<TQ> tq = _questionService.GetData();
public class TQ
{
// Index
public int i { get; set; }
// Text
public string text { get; set; }
}
How can I filter what's in tq and make another list where text is not null ?
_questionService.GetData().Where(x => x.text != null);
You might be interested in reading up on LINQ, it will be one of your most important tools in C# development.
If you can use LINQ you can use
var newList = tq.Where(p => p.text != null).ToList()
else something like that
var newList = new List<TQ>();
foreach(var element in tq) {
if (element.text != null) {
newList.Add(element);
}
}

Anonymous Delegate - Search property with collection of objects

Here is the current code in my application using an anonymous delegate to search a collection on properties:
public class MyObject
{
public MyObject() { }
public string MyObjectId { get; set; }
public List<MySubObject> SubObjects { get; set; }
}
public class MySubObject
{
public MySubObject() { }
public string MySubObjectId { get; set; }
}
public List<MyObject> Search(string input)
{
List<MyObject> AllObjects = Data.GetAllObjects();
List<MyObject> SearchResults = new List<MyObject>();
SearchResults = AllObjects.FindAll
(
delegate(MyObject o)
{
return e.MyObjectId.Equals(input)
}
);
if (SearchResults .Count.Equals(0))
SearchResults = null;
return SearchResults ;
}
I want to modify the anonymous delegate to search by the MySubObject.MySubObjectId property in the generic list instead of the MyObjectId property. How would I modify the code in the anonymous delegate to accomplish this?
Try the following
delegate(MyObject o) {
var mySubObject = o as MySubObject;
return mySubObject != null && mySubObject.MySubObjectId == input;
}
Note that you could also use shorter lambda syntax here
(o) => {
var mySubObject = o as MySubObject;
return mySubObject != null && mySubObject.MySubObjectId == input;
}
Or a LINQ query
var searchResult = AllObjects
.OfType<MySubObject>()
.Where(x => x.MySubObjectId == input)
.Cast<MyObject>()
.ToList()
Try this, using lambda expressions. Basically an object is found if at least one of its subobjects contains the required input.
SearchResults = AllObjects.Where(obj =>
obj.SubObjects != null
&& obj.SubObjects.Any(subObj => ubObj.MySubObjectId.Equals(input))
).ToList();
This looks like it could be trimmed down a lot, but you need to get rid of null assignments to the lists:
public List<MyObject> Search(string input)
{
return Data.GetAllObjects()
.Where(obj => obj.SubObjects
.Any(subobj => subobj.SubOjectId.Equals(input)));
}
.Clear() your lists instead of nullifying them, for a more consistent design and a lot less null-checking.

Iterating over class properties using LINQ

There is a ParsedTemplate class that it has over 300 property (typed Details and BlockDetails). The parsedTemplate object will be fill by a function. After filling this object I need a LINQ (or other way) to find is there any property like "body" or "img" where IsExist=false and Priority="high".
public class Details
{
public bool IsExist { get; set; }
public string Priority { get; set; }
}
public class BlockDetails : Details
{
public string Block { get; set; }
}
public class ParsedTemplate
{
public BlockDetails body { get; set; }
public BlockDetails a { get; set; }
public Details img { get; set; }
...
}
You're going to need to write your own method to make this appetizing. Fortunately, it doesn't need to be long. Something like:
static IEnumerable<Details> GetDetails(ParsedTemplate parsedTemplate)
{
return from p in typeof(ParsedTemplate).GetProperties()
where typeof(Details).IsAssignableFrom(p.PropertyType)
select (Details)p.GetValue(parsedTemplate, null);
}
You could then, if you wanted to check if any property "exists" on a ParsedTemplate object, for example, use LINQ:
var existingDetails = from d in GetDetails(parsedTemplate)
where d.IsExist
select d;
If you really wanted to use linq while doing that, you could try something like that:
bool isMatching = (from prop in typeof(ParsedTemplate).GetProperties()
where typeof(Details).IsAssignableFrom(prop.PropertyType)
let val = (Details)prop.GetValue(parsedTemplate, null)
where val != null && !val.IsExist && val.Priority == "high"
select val).Any();
Works on my machine.
Or in extension method syntax:
isMatching = typeof(ParsedTemplate).GetProperties()
.Where(prop => typeof(Details).IsAssignableFrom(prop.PropertyType))
.Select(prop => (Details)prop.GetValue(parsedTemplate, null))
.Where(val => val != null && !val.IsExist && val.Priority == "high")
.Any();
Use c# reflection. For example:
ParsedTemplate obj;
PropertyInfo pi = obj.GetType().GetProperty("img");
Details value = (Details)(pi.GetValue(obj, null));
if(value.IsExist)
{
//Do something
}
I haven't compile but i think it work.
ParsedTemplate tpl = null;
// tpl initialization
typeof(ParsedTemplate).GetProperties()
.Where(p => new [] { "name", "img" }.Contains(p.Name))
.Where(p =>
{
Details d = (Details)p.GetValue(tpl, null) as Details;
return d != null && !d.IsExist && d.Priority == "high"
});

Categories