C# AddRange List<List<T>> - c#

I need to populate List from List of List objects or List of Enumarable Objects.
Consider the class
public class Data
{
public int ID;
public List<string> Items;
}
List<Data> lstData= new List<Data>();
lstData.Add(new Data { ID = 1, Items = new List<string> { "item1", "item2" } });
lstData.Add(new Data { ID = 2, Items = new List<string> { "item3", "item4" } });
Now , I want to popuplate all the items into one list, like
List<string> values = new List<string>();
values.AddRange(lstData.Select(a => a.Items));
But I am getting error for above AddRange, pls help anyone to write AddRange for this case

Use SelectMany() to flatten a sequence of sequences:
var values = lstData.SelectMany(i => i.Items).ToList()

Related

Compare Object vs Dictionary<int,List<int>> considering performance c#

using System;
using System.Collections.Generic;
using System.Linq;
namespace ConsoleApp5
{
class Validator
{
static void Main()
{
var metaValues = new List<Meta>
{
new Meta(4, 15, true),
new Meta(5, 20, false)
};
var requestDict = new Dictionary<int, List<int>>
{
{4, new List<int>{15,20} },// error not exist
{5, new List<int>{25} }, // error its false
{6, new List<int>{30} } // error not exist
};
var matchedIds = new List<int>();
if (metaValues.Any())
{
foreach (var ob in metaValues)
{
if (requestDict.ContainsKey(ob.Id))
{
matchedIds.Add(ob.Id);
var valuesDict = requestDict[ob.Id];
//here i cant get all the values and its Active of meta.Id
}
}
}
foreach (var key in requestDict.Keys)
{
if (!matchedIds.Contains(key))
Console.WriteLine("Invalid");
}
}
}
public class Meta
{
public int Id { get; private set; }
public int Value { get; private set; }
public bool IsActive { get; private set; }
public Meta(int id, int value, bool isActive)
{
Id = id;
Value = value;
IsActive = isActive;
}
}
}
iterating dictionary with object causing performance issue since everytime dictionary key has to be iterated in an list of object so i am trying to take object and lookup in dictionary on below condition
Invalid when meta.Id does not exist in dictionary key
Invalid when one of the meta.Value does not exist in dictionary values List
Inactive when meta.Id and meta.value match with dictionary but meta.isactive is false
I probably shouldn't bother answering since:
The code is quite messy
It does not compile
The question is very unclear
However, for some reason I feel like I understand a little what you're trying to do and wanted to provide some help.
First, let's NOT name a class with the same name as a built-in type (System.Object). Perhaps Item is generic enough? Also, you appear to instantiate instances of this class by calling a constructor that doesn't exist, so let's add that constructor as well:
public class Item
{
public int Id { get; }
public int Value { get; }
public bool IsActive { get; }
public Item(int id, int value, bool isActive)
{
Id = id;
Value = value;
IsActive = isActive;
}
}
Now we can create our list of Item objects by calling the constructor:
var items = new List<Item>
{
new Item(4, 15, true),
new Item(5, 20, false)
};
It also appears that you're creating a dictionary that contains a Key of type int that maps to Item.Id, and a Value of type List<int> that sort-of maps to Item.Value (though Item.Value is a single int). A problem in the code you posted is that you're trying to add two items with the same Key value of 4, which is not legal for a Dictionary - all the keys must be unique. To fix this, I'm using unique keys:
var requests = new Dictionary<int, List<int>>
{
{4, new List<int> {15}},
{5, new List<int> {20}},
{6, new List<int> {25}},
{7, new List<int> {30}}
};
Next it appears that you're trying to create a List<int> of numbers representing the Item.Id values that exist as dictionary keys. This can be done with a System.Linq extension method:
var matchedIds = items
.Where(item => requests.ContainsKey(item.Id))
.ToList();
And finally, it's not exactly clear what you want to do with this list, but it appears you want to do something if either an Item.Id does not exist in the dictionary, or the Item.Id exists but the Item.Value is not in the list, or the item does exist, but the Item.IsActive value is false, or some other combination of these properties.
Here's how to get those items:
var matchedIds = items
.Where(item => requests.ContainsKey(item.Id))
.ToList();
var matchedIdsAndValues = matchedIds
.Where(item => requests[item.Id].Contains(item.Value))
.ToList();
var matchedIdsMissingValue = matchedIds
.Where(item => !requests[item.Id].Contains(item.Value))
.ToList();
var unmatchedIds = items
.Where(item => !requests.ContainsKey(item.Id))
.ToList();
var matchedIdAndValueButNotActive = matchedIdsAndValues
.Where(item => !item.IsActive)
.ToList();
Hope this helps!

Create default item in a list and return new item

I would like to add a new item at the back of a list, and get the newly created item.
Let's assume that we could do something like this for one moment:
class Temp
{
public string First { get;set;}
public string Second { get;set;}
}
List<string> list = new List<string>();
var newItem = list.Push();
newItem.First="asd";
newItem.Second = "qwe;
this would be easier than
var newItem = new Temp();
newItem.First="asd";
newItem.Second = "qwe;
list.Add(newItem);
especially when I can't use auto-properties.
Is this possible?
Unless you implement your own List type and add the Push method, the only way you can do that is if the T in List can be constructed using a parameterless constructor.
Here's an extension method for that.
This is not recommended, but is an answer to your question.
Something along the lines of this - I did not compile or run this code
public static class ListEx {
public static T Push<T>(this List<T> list) where T: new() {
// Create an instance of T.
var instance = new T();
// Add it to the list.
list.Add(instance);
// Return the new instance.
return instance;
}
}
You can use object initializers:
var list = new List<Temp>();
list.Add(new Temp{ First = "abc", Second = "def" });
Or together with a collection initializer:
var list = new List<Temp> { new Temp{ First = "abc", Second = "def" } };
This turns your four liner into a one liner.
Or with more than one entry:
var list = new List<Temp> {
new Temp{ First = "abc", Second = "def" },
new Temp{ First = "ghi", Second = "jkl" },
new Temp{ First = "mno", Second = "pqr" }
};
And it should of course be a list of Temp instead of a list of string.

How to get value from IEnumerable collection using its Key?

I have IEnumerable collection like following
IEnumerable<Customer> items = new Customer[]
{
new Customer { Name = "test1", Id = 999 },
new Customer { Name = "test2", Id = 989 }
};
I want to get value using key Id
I tried like following
public int GetValue(IEnumerable<T> items,string propertyName)
{
for (int i = 0; i < items.Count(); i++)
{
(typeof(T).GetType().GetProperty(propertyName).GetValue(typeof(T), null));
// I will pass propertyName as Id and want all Id propperty values
// from items collection one by one.
}
}
If you want to retrieve a Customer name from a collection by its Id:
public string GetCustomerName(IEnumerable<Customer> customers, int id)
{
return customers.First(c => c.Id == id).Name;
}
Using LINQ you can get all customers names (values) having specific value in this way:
var valuesList = items.Where(x => x.Something == myVar).Select(v => v.Name).ToList();
For single customer name you can do this:
var singleName = items.FirstOrDefault(x => x.Id == 1)?.Name;
Obviously, the Id can be 1, 2 or any other.
Edit:
I recommend you List<Customer> instead of Customer[]
So,
var items = new List<Customer>
{
new Customer { Name = "test1", Id = 999 },
new Customer { Name = "test2", Id = 989 }
};
// I will pass propertyName as Id and want all Id propperty values
// from items collection one by one.
If I understand you correctly
public static IEnumerable<object> GetValues<T>(IEnumerable<T> items, string propertyName)
{
Type type = typeof(T);
var prop = type.GetProperty(propertyName);
foreach (var item in items)
yield return prop.GetValue(item, null);
}
Just use LINQ to achieve what you want to do. if you want to retrieve a specific value you can use where like this:
public Customer GetCustomerById(IEnumerable<Customer> items,int key)
{
return items.Where(x=>x.id==key)
.Select(x =>x.Name)
.First();
}
this will retrieve the customer who match a specific Id.
Do you want to look things up repeatedly after creating the list? If so, you might want to consider creating a dictionary to do the lookups, like so:
IEnumerable<Customer> items = new Customer[]
{
new Customer {Name = "test1", Id = 999},
new Customer {Name = "test2", Id = 989}
};
var lookup = items.ToDictionary(itemKeySelector => itemKeySelector.Id);
var result = lookup[989];
Console.WriteLine(result.Name); // Prints "test2".
I'm assuming that you don't create the collection in the first place - if you had control over creating the original collection you could use a dictionary in the first place.
private TextBox [] Collectionstextboxonpanel(Panel panel)
{
var textBoxspanel1 = panel.Controls.OfType<TextBox>(); // select controls on panle1 by type
IEnumerable<TextBox> textBoxes = textBoxspanel1; // create collection if need
TextBox[] textBoxes1 = textBoxes.ToArray(); // Array collection
return textBoxes1; // get back TextBox Collection
}

To get the Data in required JSON format

My code for the object is as follows,
System.Web.Script.Serialization.JavaScriptSerializer jSearializer = new System.Web.Script.Serialization.JavaScriptSerializer();
List<object> modified_listofstrings = new List<object>();
List<string> p_Name = new List<string>();
List<float> Data = new List<float>();
List<string> s_Name = new List<string>();
List<float> p_Value = new List<float>();
var obj1=new{
Data=p_Value
};
var obj2 = new
{
Series=obj1,
};
modified_listofstrings.Add(obj1);
jSearializer.Serialize(modified_listofstrings);
and output I get is as below,
[{"Series":{"Data":[14,14,14,14,18,18,18,18,17,15,13,12]}}]
but I want output as in below format,
"Series" : [ { "Data" : [14,14,14,14,18,18,18,18,17,15,13,12,""] } ],
since I want to use the Values as series.Data... any help will be greatly appreciated,
modified_listofstrings has List type, so it always has been serialized as array. But you may serialize only first element of modified_listofstrings -
jSearializer.Serialize(modified_listofstrings[0]);
and get exactly what you want.
or another answer. just change obj1 property creating like this:
var obj1=new[] {
new { Data = p_Value }
};
Or change obj2 like this:
var obj2 = new
{
Series = new[] { obj1 }
};
Try to have your modified_listofstrings as an object and not a List. Unless you want it to be a list ofcourse. If so do a jSearializer.Serialize(modified_listofstrings[0]) as #Dmytro Rudenko suggested.
Try thinking of json to convert in form of csharp classes..
this will avoid problems
from http://json2csharp.com/
public class Series
{
public List<object> Data { get; set; }
}
public class Root
{
public List<Series> Series { get; set; }
}
now add items to collection and serialize object .. this is right approach when you serialize and deserialize object.

Is Inferred List Initializes possible?

I know that i can initialize a collection as follows
var array = []{"1", "2", "3"};
which will automatically infer that i want to create an Array of type String, But this will restrict me from Adding or removing indexes from the array since an Array has a fixed size.
Is there anyway to do the same with the Generic List type and the the compiler should infer which type "T" is based on the items in the initializer?
Maybe something like new List(){...}
No, this is not supported - you have to specify the type parameter but can still use collection initializers.
var list = new List<String> { "1", "2", "3" };
You could however create a helper method
public static class ListUtilities
{
public static List<T> New<T>(params T[] items)
{
return new List<T>(items);
}
}
and use it like this.
var list = ListUtilities.New("1", "2", "3");
But this is probably not worth it, you don't gain much if anything at all. And this will create an array first and use it to populate a list. So this is not that different from Keith Nicholas' var list = new[] { "1", "2", "3" }.ToList();.
Here's a pretty nifty example:
static void Main(string[] args)
{
var Customer = new { FirstName = "John", LastName = "Doe" };
var customerList = MakeList(Customer);
customerList.Add(new { FirstName = "Bill", LastName = "Smith" });
}
public static List<T> MakeList<T>(T itemOftype)
{
List<T> newList = new List<T>();
return newList;
}
http://kirillosenkov.blogspot.com/2008/01/how-to-create-generic-list-of-anonymous.html
var list = new[] {"1", "2", "3"}.ToList();
Yes. But no inference .
var li = new List<int> {1,2,3,4,5,6};
Closest you will get is
var li = new List<dynamic> {1,2,3,4,5}

Categories

Resources