Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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 }
// ]
like image 459
jhonly Avatar asked Jun 23 '15 19:06

jhonly


People also ask

How to get a subset of a JavaScript object's properties?

To get the subset of properties of a JavaScript Object, we make use of destructuring and Property Shorthand. The destructuring assignment syntax is a JavaScript expression that makes it possible to unpack values from arrays, or properties from objects, into distinct variables.


2 Answers

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}]

like image 149
Hamid Pourjam Avatar answered Oct 08 '22 15:10

Hamid Pourjam


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.

like image 1
willaien Avatar answered Oct 08 '22 15:10

willaien