Convert from List of string array to List of objects - c#

If I have a simple class that looks like this:
public string Param1 { get; set; }
public string Param2 { get; set; }
public SimpleClass (string a, string b) { Param1 = a; Param2 = b; }
List of string array returned from another class:
var list = new List<string[]> {new[] {"first", "second"}, new[] {"third", "fourth"}};
Is there a more efficient way using C# to end up with List<SimpleClass> without doing something like:
var list1 = new List<SimpleClass>();
foreach (var i in list)
{
var data = new SimpleClass(i[0], i[1]);
list1.Add(data);
}

You can use Linq:
var simpleClassList = originalList.Select(x => new SimpleClass(x[0], x[1])).ToList()

As was said by #rualmar you can use linq. But you also can overload implicit operator.
For example
public static implicit operator SimpleClass(string[] arr)
{
return new SimpleClass(arr[0], arr[1]);
}
and after that you can write this
var list = new List<SimpleClass> { new[] { "first", "second" }, new[] { "third", "fourth" } };

Related

Converting or casting List<sting> to List<type> in c#

Looking for direct way to convert/cast all elements of List<string> to a list of particular type which has one string property.
Type Class with one string property:
public class ClaimNumber
{
public string claimNumber { get; set; }
}
The List I receive from webservice is in List<string> format.
I need to convert/cast List<string> to List<ClaimNumber>
Tried as multiple suggessions given in Shorter syntax for casting from a List<X> to a List<Y>?, but those did not work in above case. Please suggest the right way to achieve this.
Simply run through each element and create a new ClaimNumber object, populating the property.
With Linq:
// List<string> source = ...
List<ClaimNumber> claims = source.Select(s => new ClaimNumber { claimNumber = s }).ToList();
With a foreach
// List<string> source = ...
List<ClaimNumber> claims = new();
foreach (var s in source)
{
claims.Add(new ClaimNumber { claimNumber = s });
}
Here is how you can do this:
void Main()
{
List<string> c1List = new List<string>();
List<ClaimNumber> c2List = new List<ClaimNumber>();
c1List.Add("1234");
c1List.Add("4321");
c1List.Add("1111");
c1List.Add("9999");
c2List.AddRange(c1List.Select(x => new ClaimNumber
{
claimNumber = x
}));
}
public class ClaimNumber
{
public string claimNumber { get; set; }
}
This returns:

Nested Json array in MVC Controller

Pretty silly question to ask. but could not figure it out .
In a C# MVC Controller action , I need to model a Json Array for testing purposes.
But this shows me compilation errors instead of being a valid Json:
var result = {
"controllerId": "controller1",
"controllerName": "ControllerOne"
};
But this is perfectly valid :
var scheduleResult = new[]
{
new { scheduleId = "schedule1",scheduleName = "scheduleOne"},
new { scheduleId = "schedule2",scheduleName = "scheduleTwo"}
};
Why so ?
Also how to write a nested Json array :
I tried :
var scheduleResult = new[]
{
new { scheduleId = "schedule1",scheduleName = "scheduleOne",new[]{ new {doorId="Door1",doorName="DoorOne"}, new { doorId = "Door2", doorName = "DoorTwo" } } },
new { scheduleId = "schedule2",scheduleName = "scheduleTwo"}
};
But it shows errors in syntax. What to do ?
I Need to have nested array within each element of that array .
Thanks in advance.
Well, C# does not support the way you wrote. You can't just type in JSON in C# and expect it to work unfortunately. You can try like that with anonymous type:
var result = new
{
controllerId = "controller1",
controllerName = "ControllerOne",
myArray = new []
{
"a",
"b"
}
};
This is converted to JSON no problem if you return it as a result of API call.
The nested arrays you are talking about don't work because you need to give them a name, you can't have array property without a name. See example above.
Why don't you use Dictionary<TKey, TValue> with Newtonsoft.Json?
Simple json:
IDictionary<string, string> obj = new Dictionary<string, string>();
obj.Add("controllerId", "controller1");
obj.Add("controllerName", "ControllerOne");
// {"controllerId":"controller1","controllerName":"ControllerOne"}
string json = JsonConvert.SerializeObject(obj);
Nested json:
IList<string> obj = new List<string>();
IDictionary<string, string> first = new Dictionary<string, string>();
first.Add("scheduleId ", "schedule1");
first.Add("scheduleName", "scheduleOne");
IDictionary<string, string> second = new Dictionary<string, string>();
second.Add("scheduleId ", "schedule2");
second.Add("scheduleName", "scheduleTwo");
string first_json = JsonConvert.SerializeObject(first);
string second_json = JsonConvert.SerializeObject(second);
obj.Add(first_json);
obj.Add(second_json);
// ["{\"scheduleId \":\"schedule1\",\"scheduleName\":\"scheduleOne\"}","{\"scheduleId \":\"schedule2\",\"scheduleName\":\"scheduleTwo\"}"]
string json = JsonConvert.SerializeObject(obj);
Here first of all we should create model class with the same pattern of our return type
public class ScheduleModel
{
public List<Schedule> ScheduleList { get; set; }
}
public class Schedule
{
public int ScheduleId { get; set; }
public string ScheduleName { get; set; }
public List<Door> DoorList { get; set; }
}
public class Door
{
public int DoorId { get; set; }
public string DoorName { get; set; }
}
Now at the controller Action create the test data
List<Door> doorList = new List<Door>();
doorList.Add(new Door{DoorId = "Door1",DoorName = "DoorOne"});
doorList.Add(new Door{DoorId = "Door2",DoorName = "DoorTwo"});
List<Schedule> scheduleList = new List<Schedule>();
scheduleList.Add(new Schedule{
ScheduleId = "schedule1",
ScheduleName = "scheduleOne",
DoorList = doorList
});
scheduleList.Add(new Schedule
{
ScheduleId = "schedule2",
ScheduleName = "scheduleTwo",
});
return Json(scheduleList, JsonRequestBehavior.AllowGet);
If this answer benefits you please mark as an answer.

Create a subset of an object based off an array of property names

I have a class and an array of property names defined as follows:
public class Dog {
public string Name { get; set; }
public string Breed { get; set; }
public int Age { get; set; }
}
var desiredProperties = new [] {"Name", "Breed"};
I also have a method that returns a list of dog objects:
List<Dog> dogs = GetAllDogs();
Is there an way I can return a subset of dogs that only contain the properties defined within the desiredProperties array? Eventually, this resulting list will be serialized to JSON.
I have been struggling with this problem for some time now, considering that the user will be allowed to specify any combination of properties (assuming they are all valid) as the output within the array. Some more examples:
var desiredProperties = new [] {"Name", "Age"};
// Sample output, when serialized to JSON:
// [
// { Name: "Max", Age: 5 },
// { Name: "Spot", Age: 2 }
// ]
var desiredProperties = new [] {"Breed", "Age"};
// [
// { Breed: "Scottish Terrier", Age: 5 },
// { Breed: "Cairn Terrier", Age: 2 }
// ]
you can write a function to do that. Use the extension method below.
public static class Extensions
{
public static object GetPropertyValue(this object obj, string propertyName)
{
return obj.GetType().GetProperty(propertyName).GetValue(obj);
}
public static List<Dictionary<string, object>> FilterProperties<T>(this IEnumerable<T> input, IEnumerable<string> properties)
{
return input.Select(x =>
{
var d = new Dictionary<string, object>();
foreach (var p in properties)
{
d[p] = x.GetPropertyValue(p);
}
return d;
}).ToList();
}
}
Test it like
var dogs = GetAllDogs();
var f1 = dogs.FilterProperties(new[]
{
"Name", "Age"
});
var f2 = dogs.FilterProperties(new[]
{
"Breed", "Age"
});
Console.WriteLine(JsonConvert.SerializeObject(f1));
Console.WriteLine(JsonConvert.SerializeObject(f2));
and result is
[{"Name":"Spot","Age":2},{"Name":"Max","Age":5}]
[{"Breed":"Cairn Terrier","Age":2},{"Breed":"Scottish Terrier","Age":5}]
I don't have a clue if this is the most efficient way to do it, but it's a way of doing it:
var list = new List<Dog>();
list.Add(new Dog {Name = "Max", Breed = "Bull Terrier", Age = 5});
list.Add(new Dog {Name = "Woofie", Breed = "Collie", Age = 3});
var desiredProperties = new[] {"Name", "Breed"};
var exportDogs = new List<Dictionary<string, object>>();
foreach(var dog in list)
{
var exportDog = new Dictionary<string, object>();
foreach(var property in desiredProperties)
{
exportDog[property] = dog.GetType().GetProperty(property).GetValue(dog, null);
}
exportDogs.Add(exportDog);
}
var output = JsonConvert.SerializeObject(exportDogs);
The output will look like this:
[{"Name":"Max","Breed":"Bull Terrier"},{"Name":"Woofie","Breed":"Collie"}]
If, however, you don't need to dynamically access properties, it's a lot better to do something like this:
var output = list.Select(dog => new {dog.Name, dog.Breed});
Then just serialize the output.
something like this...not tested...
var desiredProperties = new [] {"Name", "Breed"};
var lst = (from asm in AppDomain.CurrentDomain.GetAssemblies()
from asmTyp in asm.GetTypes()
where typeof(dog).IsAssignableFrom(asmTyp) && desiredProperties.All(p=> PropertyExists(asmTyp, p))
select asmTyp).ToArray();
private bool PropertyExists(Type dogType, string name)
{
bool ret=true;
try{ dogType.GetProperty(name);}
catch{ret=false};
return ret;
}

generate all possible combinations for a dynamic list of attributes with their values

I struggle with generating all possible combinations for a List of Attributes with their possible values. What I would like to implement is a Method like this:
public List<Variant> generateAllPossibleVariants(List<Attribute> attributes)
The Attribute Class looks the following:
public class Attribute {
public String Name { get; set; }
public ICollection<String> PossibleValues { get; protected set; }
}
So imagine you have a list of 2 Attributes (while the count is dynamic) with their possible values:
attributeColor with possible Values of ( "red", "blue" )
attributeSize with possible values of ("XL", "L" )
Now my method should return a List of Variant while the Variant Class looks the following:
public class Variant
{
public IDictionary<Attribute, string> AttributeValues { get; private set; }
}
Now my method should return a List of all combinations like the following:
List<Variant> :
Variant.AttributeValues { attributeColor => "red", attributeSize => "XL" }
Variant.AttributeValues { attributeColor => "red", attributeSize => "L" }
Variant.AttributeValues { attributeColor => "blue", attributeSize => "XL" }
Variant.AttributeValues { attributeColor => "blue", attributeSize => "L" }
This is not an optimized code, but you can get the idea and clean it up yourself:
public void Main()
{
var attr1 = new MyAttribute { Name = "Colors", PossibleValues = new List<string> { "red", "blue" } };
var attr2 = new MyAttribute { Name = "Sizes", PossibleValues = new List<string> { "XL", "L" } };
var attr3 = new MyAttribute { Name = "Shapes", PossibleValues = new List<string> { "qube", "circle" } };
var attrList = new List<MyAttribute> { attr1, attr2, attr3 };
var result = attrList.Skip(1).Aggregate<MyAttribute, List<Variant>>(
new List<Variant>(attrList[0].PossibleValues.Select(s => new Variant { AttributeValues = new Dictionary<MyAttribute, string> { {attrList[0], s} } })),
(acc, atr) =>
{
var aggregateResult = new List<Variant>();
foreach (var createdVariant in acc)
{
foreach (var possibleValue in atr.PossibleValues)
{
var newVariant = new Variant { AttributeValues = new Dictionary<MyAttribute, string>(createdVariant.AttributeValues) };
newVariant.AttributeValues[atr] = possibleValue;
aggregateResult.Add(newVariant);
}
}
return aggregateResult;
});
}
public class MyAttribute
{
public string Name { get; set; }
public ICollection<string> PossibleValues { get; set; }
}
public class Variant
{
public IDictionary<MyAttribute, string> AttributeValues { get; set; }
}
You are looking for cartesian product (with dynamic dimension).
One simple way to achieve it is using recursion on the dimension, and each time invoke cartesian product on the result of the recursion, and one of the dimensions.
Pseudo code:
genAllPossibilities(list attributes) //each element in attributes is a list
if length(attributes) == 1:
return attributes[0] //the only element, which is a list of one attribute
else:
curr = head(attributes) // first element in the list
reminder = tails(attributes) // a list of all elements except the first
return cartesianProduct(genAllPossibilities(reminder), curr)
cartesianProduct(list1, list2):
l = new list
for each x1 in list1:
for each x2 in list2:
l.append(new MyObject(x1,x2))
return l

Convert Lambda into Linq Statement with nested for loop

Is there a way to rewrite the GetTransformedCollection method below so that it uses a Linq statement and not an expression? I'm currently trying to get around the “A lambda expression with a statement body cannot be converted to an expression tree” error.
public class Obj1
{
public int Id { get; set; }
public string[] Names { get; set; }
public string[] Tags { get; set; }
}
public class EntCollections
{
private List<Obj1> _results;
[SetUp]
public void SetUp()
{
_results = new List<Obj1>
{
new Obj1 {Id = 1, Names = new[] {"n1"}, Tags = new[] {"abc", "def"}},
new Obj1 {Id = 2, Names = new[] {"n2", "n3"}, Tags = new[] {"ghi"}},
new Obj1 {Id = 3, Names = new[] {"n1", "n3"}, Tags = new[] {"def", "xyz"}}
};
}
private static Dictionary<string, List<string>>
GetTransformedCollection(IEnumerable<Obj1> results)
{
var list = new Dictionary<string, List<string>>();
foreach (var result in results)
{
foreach (var id in result.Names)
{
if (list.ContainsKey(id))
{
list[id].AddRange(result.Tags);
}
else
{
list.Add(id, result.Tags.ToList());
}
}
}
return list;
}
[Test]
public void Test()
{
var list = GetTransformedCollection(_results);
Assert.That(list["n1"], Is.EquivalentTo(new [] { "abc", "def", "def", "xyz" }));
Assert.That(list["n2"], Is.EquivalentTo(new [] { "ghi" }));
Assert.That(list["n3"], Is.EquivalentTo(new [] { "ghi", "def", "xyz" }));
}
P.s I'm not too worried about the result type being a Dictionary, that was just the simplist way to express it as a return type.
I would personally use an ILookup, which is a good bet whenever you have a Dictionary<T1, List<T2>>, and is built with ToLookup():
// Flatten the objects (lazily) to create a sequence of valid name/tag pairs
var pairs = from result in results
from name in result.Names
from tag in result.Tags
select new { name, tag };
// Build a lookup from name to all tags with that name
var lookup = pairs.ToLookup(pair => pair.name, pair => pair.tag);
Idea is to find all keys for resulting dictionary and then find corresponding values from original sequence of Obj1
var distinctNames = results.SelectMany(val => val.Names).Distinct();
return distinctNames
.ToDictionary(name => name,
name => results
.Where(res => res.Names.Contains(name))
.SelectMany(res => res.Tags)
.ToList());

Categories

Resources