remove null column from collection in c# - c#

I have a table Menu and the data is like the attached screen shot
Database table
and I want output like below image,
Means all the null values or integer ==0 should be hidden.
Right now I am showing these 5 columns only as you can see in 2nd screen shot..
I have something like this..
List<Menu> lstMenus = obj.GetMenus(10);
My code is
var menus = new List< dynamic >();
foreach (Menu menuBE in lstMenus)
{
dynamic menu = new
{
menuBE.MenuID,
menuBE.ParentMenuID,
menuBE.LinkText,
menuBE.ScreenName,
menuBE.Parameters,
menuBE.URL
// if(menuBE.Parameters.Length>0 ){ Parameters = menuBE.Parameters,}
};
menus.Add(menu);
}
and I want to put some condition like the last commented line in foreach loop. If menuBE.Parameters.Length>0 then this Parameters column should add be in dynamic menu else not.
Any idea how it can be done?

What I understood, in the opposite of James & techloverr, you want to keep records with parameter null:
foreach (Menu menuBE in lstMenus){
if (menuBE.Parameters.Length > 0){
dynamic menu = new{
menuBE.MenuID,
menuBE.ParentMenuID,
menuBE.LinkText,
menuBE.ScreenName,
menuBE.Parameters,
menuBE.URL
};
}
else {
dynamic menu = new{
menuBE.MenuID,
menuBE.ParentMenuID,
menuBE.LinkText,
menuBE.ScreenName,
menuBE.URL
};
}
menus.Add(menu);
}
** UPDATE **
As I understand in the whole question, you do not want a property Parameters when source data have Parameters.Lenght == 0, and that's why you are using dynamic type.
It's different from "that's OK have a property 'Parameters = null'". If that's the approach, you don't need to use dynamic type. Just add items as list-item of a declarated strong-type variable or list-item of anonymous type.
With the dynamic type you add properties at declaration time. So, you have to separate the different assigns as the code above.
If you want to put if outside to avoid duplicate code, you use ExpandoObject:
var m = new List<System.Dynamic.ExpandoObject>();
foreach (string item in new string[] { "a", "b", "c" }) {
dynamic menuItem = new System.Dynamic.ExpandoObject();
menuItem.pos1 = item;
menuItem.pos2 = (item == "b" ? item : null); // wrong
if (item == "c") { // correct
menuItem.pos3 = "I am at third iteration";
}
m.Add(menuItem);
}
See, if you put a breakpoint at m.Add(menuItem); these are the results:
case item == "a":
menuItem.pos1 = "a";
menuItem.pos2 = null; // wrong: pos2 must not exists
case item == "b":
menuItem.pos1 = "b";
menuItem.pos2 = "b";
case item == "c":
menuItem.pos1 = "c";
menuItem.pos2 = null; // wrong: pos2 must not exists
menuItem.pos3 = "I am at third iteration"; // correct: pos3 only exists here.

you can use this code snippet
foreach (Menu menuBE in lstMenus)
{
dynamic menu = new
{
MenuID = menuBE.MenuID,
ParentMenuID = menuBE.ParentMenuID,
LinkText = menuBE.LinkText,
ScreenName = menuBE.ScreenName,
URL = menuBE.URL,
Parameters = (menuBE.Parameters.Length>0) ? menuBE.Parameters : null
};
menus.Add(menu);
}

Related

.Net Core, merge two lists, remove invalid entries and keep values in the original list

I have a default list of attributes and in incoming list of attributes. I need to remove any items from the incoming list that do now match the Name in the default list. I have tried many different LINQ queries, but have not been able to accomplish this task.
Default List:
Attributes[] defaultAttributes =
{
new ProfileAttributes() { Name = "FirstName", Include = false, Required = false },
new ProfileAttributes() { Name = "MiddleName", Include = false, Required = false },
new ProfileAttributes() { Name = "HomeCountry", Include = false, Required = false },
...
I want to merge the two lists and remove any items where the Name of the incoming list does not match the default list.
For example in the following remove Favorite color because it is an invalid name and preserve the required values.
Attributes[] incomingAttributes =
{
new ProfileAttributes() { Name = "FavoriteColor", Required = true },
new ProfileAttributes() { Name = "MiddleName", Required = false},
new ProfileAttributes() { Name = "HomeCountry", Required = true },
Most incoming lists will not have "Include" So I need to add that and set it to true if it is in the incoming list, otherwise false. I have done that with the following, but interested if there is a way to combine this with the merge.
Revised, I used the following solution:
I used lists instead of array lists. I found this easier to loop through and bind to checkboxes on the form
Attributes[] defaultAttributes
to
List<ProfileAttributes> defaultAttributes = new List<ProfileAttributes>()
Inside the loop for my form:
<input type="checkbox"for="myModel.ProfileAttributes[i].Include"
I created an empty list:
List<ProfileAttributes> validListAttributes = new();
Then I created a loop. If the name is valid add it to the empty list and add the Include attribute:
foreach (var a in myModel.ProfileAttributes) //incomingAttributes
{
if (defaultAttributes.Any(d => d.Name == a.Name))
{
a.Include = true;
validListAttributes.Add(a);
}
}
Then another loop to add missing attributes because all attributes must be display on the form:
foreach (var d in defaultAttributes)
{
if (!validListAttributes.Any(v => v.Name == d.Name))
{
validListAttributes.Add(d);
}
}
Then update the model with the valid list containing all attributes:
myModel.ProfileAttributes = validListAttributes.ToList();
This will be a lot easier with a generic IEqualityComparer whose job is to compare the Name property of the instances involved in the process.
So let's define an IEqualityComparer for the Attributes class
public class ProfileAttributesComparer : IEqualityComparer<ProfileAttributes>
{
public bool Equals(ProfileAttributes obj1, ProfileAttributes obj2)
{
if(obj1 == null && obj2 == null)
return true;
if(obj1 == null || obj2 == null)
return false;
var result = string.Compare(obj1.Name, obj2.Name,
StringComparison.CurrentCultureIgnoreCase);
return result == 0;
}
public int GetHashCode(ProfileAttributes obj)
{
return obj.Name.GetHashCode();
}
}
Now you can process the elements in the incomingAttributes that have a name equal to an instance inside the defaultAttributes and change the property Include to true
var result = incomingAttributes
.Where(x => defaultAttributes.Contains(x, new ProfileAttributesComparer()))
.Select(p => { p.Include = true; return p;});
The result variable contains only the items with the same name but the incomingAttributes list still has three items and two of them have the Include property changed to true.

Passing multiple values to same column in the lambda query C#

Hello I am trying to create a query where in the where clause i need to pass multiple values to the same column and i have built a query using string builder.
My actual Lambda query was
crentitiesbkp.Filter = obj =>
{
SPFetchCREntity entity = obj as SPFetchCREntity;
return obj.ToString() != null && entity.SW_Version==getmuid;
};
Here i changed the entity.SW_Version==getmuid like this
crentitiesbkp.Filter = obj =>
{
SPFetchCREntity entity = obj as SPFetchCREntity;
return obj.ToString() != null + cquery.ToString();
};
so the cquery is built and looks like this
&& entity.SW_Version=="TEST" && entity.SW_Version=="Result"
But its not filtering as per the query. Is this because this is passed as string ?
The cquery is built like this
foreach (var objj in storemuid)
{
cquery.Append(" && entity.SW_Version ==" +"\""+ objj.Value + "\"");
}
I resolved this scenario by using dictionary
Dictionary<string, List<SPFetchCREntity>> objDic = new Dictionary<string, List<SPFetchCREntity>>();
List<SPFetchCREntity> sp = new List<SPFetchCREntity>();
foreach (string str in objDic.Keys)
{
sp.AddRange(objDic[str]);
}
CRmappings2 = new ObservableCollection<SPFetchCREntity>(sp.ToList());
crentitiesbkp = CollectionViewSource.GetDefaultView(CRmappings2);
}
So now based on my checkbox selection i remove and add values from dictionary which works perfect for me now. This can be of any help to starter programmers like me .

ASP.NET MVC Select list value using key

I am still reasonably new to C# and trying to understand list objects.
I have a list object with key/value pairs in it, populated from a database (that part is working). I then want to select a value from that list, using the 'key'. From what I have read I think Linq might be the best way to do this, however I cannot quite work out the syntax I need.
I have a list object as follows:
// Create a list of Items from the database, where Value is the 'key' and Text is the 'value'
IEnumerable<SelectListItem> ItemList = dbLists.ItemList.Select(x => new SelectListItem { Text = x.Description, Value = x.Id.ToString() });
I then want to populate another variable with the description of the selected item in the model, where the model only saves the id.
I have tried various linq Where and Select queries, but cannot work it out.
The easiest way I can think to explain what I am trying to achieve is to use sql syntax,
string SelectedItemDescription = SELECT Text FROM ItemList WHERE ItemList.Value = model.ItemCode
An example of a scenario would be something like:
ItemList
{
(Value = "1", Text = "Item 1"),
(Value = "2", Text = "Item 2"),
(Value = "3", Text = "Item 3"),
...
};
model.ItemCode = 2;
// How do I make:
SelectedItemDesctiption = "Item 2";
Hopefully that makes sense..
Thanks.
you can do like this in LINQ, if you write it this way:
string SelectedItemDescription = (from list in ItemList
where list.Value = model.ItemCode
select list.Text).FirstOrDefault();
or you can Use Extension Methods, If it will always return a single element then you can use SingleOrDefault():
SelectListItem SelectedItemDescription = ItemList.SingleOrDefault(item=>item.Value == model.ItemCode);
if(SelectedItemDescription !=null)
{
string Key = SelectedItemDescription .Value;
string Text = SelectedItemDescription.Text;
}
If it will return a multiple objects then you can use FirstOrDefault():
SelectListItem SelectedItemDescription = ItemList.FirstOrDefault(item=>item.Value == model.ItemCode);
if(SelectedItemDescription !=null)
{
string Key = SelectedItemDescription .Value;
string Text = SelectedItemDescription.Text;
}
UPDATED:
As #CodeGeek suggested in comments, you can also do like this:
string SelectedItemDescription =ItemList
.SingleOrDefault(item=>item.Value == model.ItemCode)!=null ? ItemList.SingleOrDefault(item=>item.Value == model.ItemCode).Text : String.Empty;

Assigning properties to an object

Okay so I have a small section of code which creates a list of objects based on the data model. I don't want to have to create a class for this. It is used on n ASP.net MVC application for populating a user notifications list.
I know there are plenty of other ways to do this such as actually setting up a class for it(probably the easiest method), but I would like to know if there is a way to do what is displayed below.
List<object> notificationList = new List<object>();
object userNotification = new { Text = "Here is some text!", Url = "http://www.google.com/#q=notifications" };
notificationList.Add(userNotification);
foreach(object notification in notificationList)
{
string value = notification.Text;
}
So I haven't populated the list much but for the purposes here you get the idea. After debug I notice that the Text and Url properties exist, however cannot code to get the values???
You need to use dynamic as variable type in the foreach:
foreach(dynamic notification in notificationList)
{
string value = notification.Text;
}
Edit Oops ... you do need "dynamic", either as the List's generic type, or in the foreach.
var notificationList = new List<dynamic>();
var userNotification = new { Text = "Here is some text!", Url = "http://www.google.com/#q=notifications" };
notificationList.Add(userNotification);
foreach (var notification in notificationList)
{
string value = notification.Text;
}
End edit
Anonymous types should be declared using the var keyword:
var userNotification = new { Text = "Here is some text!", Url = "http://www.google.com/#q=notifications" };
You could also use "dynamic" instead of "var", but that deprives you of compile-time checks, and it appears unnecessary in this case (because the type is fully defined at compile time, within the same method scope). A case where you would need to use "dynamic" is where you want to pass the anonymous-typed object as a parameter to another function, eg:
void Func1()
{
var userNotification = new { Text = "Here is some text!", Url = "http://www.google.com/#q=notifications" };
Func2(userNotification);
}
void Func2(dynamic userNotification)
{
string value = notification.Text;
}
Well you could declare the list as an list of dynimac objects:
List<dynamic> notificationList = new List<object>();
var userNotification = new { Text = "Here is some text!", Url = "http://www.google.com/#q=notifications" };
notificationList.Add(userNotification);
foreach(dynamic notification in notificationList)
{
string value = notification.Text;
}
or use var to let the compiler choose the type:
var notificationList = new []
{
new { Text = "Here is some text!", Url = "http://www.google.com/#q=notifications" }
}.ToList();
foreach(var notification in notificationList)
{
string value = notification.Text;
}

Using Contains() list method to evaluate list contents

I have a list that contains 3 items, two of type_1, and one of type_2. I want to return a second list that contains the type and number of that type that exists. When stepping through the breakpoints set at the foreach loop, the IF statement is never true. I assume there is something wrong with my attempt to use Contains() method.
The output should be something like:
type_1 2
type_2 1
Instead, it evaluates as:
type_1 1
type_1 1
type_2 1
Is my use of Contains() not correct?
public List<item_count> QueryGraphListingsNewAccountReport()
List<item> result = new List<items>();
var type_item1 = new item { account_type = "Type_1" };
var type_item2 = new item { account_type = "Type_1" };
var type_item3 = new item { account_type = "Type_2" };
result.Add(type_item1);
result.Add(type_item2);
result.Add(type_item3);
//Create a empty list that will hold the account_type AND a count of how many of that type exists:
List<item_count> result_count = new List<item_count>();
foreach (var item in result)
{
if (result_count.Contains(new item_count { account_type = item.account_type, count = 1 } ) == true)
{
var result_item = result_count.Find(x => x.account_type == item.account_type);
result_item.count += 1;
result_count.Add(result_item);
}
else
{
var result_item = new item_count { account_type = item.account_type, count = 1 };
result_count.Add(result_item);
}
}
return result_count;
}
public class item
{
public string account_type { get; set; }
}
public class item_count
{
public int count {get; set;}
public string account_type { get; set; }
}
I think your problem is that you don't want to use contains at all. You are creating a new object in your contains statement and, obviously, it isn't contained in your list already because you only just created it. The comparison is comparing references, not values.
Why not just use the find statement that you do in the next line instead? If it returns null, then you know there isn't an item already with that type.
So you could do something like this:
var result_item = result_count.Find(x => x.account_type == item.account_type);
if (result_item != null)
{
result_item.count++;
// note here you don't need to add it back to the list!
}
else
{
// create your new result_item here and add it to your list.
}
Note: Find is o(n), so this might not scale well if you have a really large set of types. In that case, you might be better off with Saeed's suggestion of grouping.
You can do:
myList.GroupBy(x=>x.type).Select(x=>new {x.Key, x.Count()});
If you want use for loop, it's better to use linq Count function to achieve this, If you want use Contains you should implement equal operator as the way you used.

Categories