How do I uncompress an array in C#? - c#

I'm running out of ideas on how to uncompress an array (request array A[] to response array B[])
Here are my definitions
A is a request class.
class A
{
public string Date { get; set; }
public decimal Price { get; set; }
}
Below is my array of requests of class A with its initalization.
var request = new A[]
{
new A { Date = "14-04-2016", Price = 100 },
new A { Date = "15-04-2016", Price = 100 },
new A { Date = "16-04-2016", Price = 0 },
new A { Date = "17-04-2016", Price = 100 },
new A { Date = "18-04-2016", Price = 100 }
};
B is a respond class.
class B
{
public string Start { get; set; }
public string End { get; set; }
public decimal Price { get; set; }
}
The above requests needs to be converted to an array of B. Something like this
var response = new B[]
{
new B { Start = "14-04-2016", End = "16-04-2016", Price = 100 },
new B { Start = "16-04-2016", End = "17-04-2016", Price = 0 },
new B { Start = "17-04-2016", End = "18-04-2016", Price = 100 }
};
The response is grouped based on the Price and order by date. Its more of like, I need to uncompress the request array A[] into response array B[].
How can I achieve this?

You could do this using GroupBy linq extension, following query returns List<B>objects.
var results = request.Select(s=>
new
{
Price = s.Price,
Date = DateTime.ParseExact(s.Date, "dd-MM-yyyy", null) // convert to Date.
})
.GroupBy(g=>g.Price)
.Select(s=>
new B()
{
Start = s.Min(c=>c.Date).ToString("dd-MM-yyyy"),
End = s.Max(c=>c.Date).ToString("dd-MM-yyyy"),
Price = s.Key
})
.ToList() ;
Update :
As per comments, you don't really require grouping on price. What you need is grouping adjacent items whose price is matching .
We could achieve this with slight modification to above Linq query.
int grp = 0;
decimal prevprice=response.First().Price;
var results = request.Select((s, i)=>
{
grp = s.Price == prevprice? grp : ++grp;
prevprice = s.Price;
return new
{
grp,
Price = s.Price,
Date = DateTime.ParseExact(s.Date, "dd-MM-yyyy", null)
};
})
.GroupBy(g=>g.grp)
.Select(s=>
new B()
{
Start = s.Min(c=>c.Date).ToString("dd-MM-yyyy"),
End = s.Max(c=>c.Date).ToString("dd-MM-yyyy"),
Price = s.First().Price
});
Output
14-04-2016,15-04-2016 ,100
16-04-2016,16-04-2016 ,0
17-04-2016,18-04-2016 ,100
Working Example

Pseudocode (assumes request is ordered by date - if not you can sort it easily):
int lastPrice = -1;
//count the distinct price ranges
int responseSize = 0;
foreach (A requestObj in request) {
if (requestObj.price != lastPrice) {
responseSize++;
lastPrice = requestObj.price;
}
}
//set the initial element
B[] response = new B[responseSize];
response[0].start = request[0].date;
response[0].price = request[0].price;
int responseindex = 0;
//parse the result
foreach (A requestObj in request) {
if (requestObj.price != response[responseindex].price) {
response[responseindex].end = requestObj.date;
responseIndex++;
response[responseindex].price = requestObj.price;
response[responseindex].start= requestObj.date;
}
}
//set the end date of the final object
response[response.length - 1].end = request[request.length - 1].date;

This can also be done with the following:
var response = from reqItem in request
group reqItem by reqItem.Price into g
select new B()
{
Start = g.Min(m => DateTime.Parse(m.Date)).ToString("dd-MM-yyyy"),
End = g.Max(m => DateTime.Parse(m.Date)).ToString("dd-MM-yyyy"),
Price = g.Key
};

Related

How to dynamically group a list and select values using linq query in C#?

I have an input list test
class Tracker
{
public string Toolid {get;set;}
public string Description {get;set;}
public int length {get;set;}
public int breadth {get;set;}
public int height {get;set;}
}
List<Tracker> test = new List<Tracker>();
test.Add( new Tracker {Toolid="A.1",Description ="ABC",length = 10, breadth =10,height = 50});
test.Add( new Tracker {Toolid="A.1",Description ="ABC", length = 10, breadth =10,height = 50});
test.Add( new Tracker {Toolid="C.1",Description ="ABCD", length = 10, breadth =10,height = 50});
test.Add( new Tracker {Toolid="D.1",Description ="Admin123", length = 10, breadth =10,height = 50});
This list contain more values like weight, colour etc.
For better understanding I have added only 5 member variables in the class Tracker.
I need to Group the list test based on the values of another list (grpList).
This list (grpList ) is dynamic, hence the number of parameter and values in the list may change.
So I need a dynamic Group By of list using LINQ query.
case 1 : sometimes this list grpList contain 2 values .
List <string> grpList = new List<string>();
grpList.Add(ToolId);
grpList.Add(Description);
if So , I have to group the list test with ToolId and Description,
case 2 : if list grpList contain N values , I have to group the list test with 'N' values .
The number of values in the grpList varies. I have group the main list test using the values in grpList. If grpList contain 2 values ,group the test list with 2 values . if If grpList contain 5 values , group the test list with 5 values.
NB : I need to Group the list test ( Main list).
grpList values only for grouping .
try reflection:
List<string> grpList = new List<string>();
grpList.Add("Toolid");
grpList.Add("Description");
var groups = new Dictionary<string, IEnumerable>();
var all_properties = typeof(Tracker).GetProperties();
foreach ( var prop_name in grpList )
{
var prop = all_properties.First( x => x.Name == prop_name);
var group = test.GroupBy( x => prop.GetValue( x ) );
groups.Add( prop_name, group );
}
if you want to have an sql-like nested grouping, apply the GroupBy to the resulting groups:
var groups = new List<List<Tracker>>() { test };
foreach ( var prop_name in grpList )
{
var prop = all_properties.First( x => x.Name == prop_name);
var newgroups = new List<List<Tracker>>();
foreach ( var group in groups)
{
var subgroups = group.GroupBy( x => prop.GetValue( x ) );
newgroups.AddRange( subgroups.Select(g => g.ToList()).ToList() );
}
groups = newgroups;
}
I used Enumerable.GroupBy Method selector predicate.
Here's how I generated the predicate and the solution seems to work.
public class Tracker
{
public string Toolid { get; set; }
public string Description { get; set; }
public int length { get; set; }
public int breadth { get; set; }
public int height { get; set; }
}
class Program
{
static void Main(string[] args)
{
List<Tracker> test = new List<Tracker>();
test.Add(new Tracker { Toolid = "A.1", Description = "ABC", length = 50, breadth = 10, height = 50 });
test.Add(new Tracker { Toolid = "A.1", Description = "ABC", length = 20, breadth = 10, height = 50 });
test.Add(new Tracker { Toolid = "C.1", Description = "LMN", length = 10, breadth = 10, height = 50 });
test.Add(new Tracker { Toolid = "D.1", Description = "Admin123", length = 7, breadth = 10, height = 50 });
List<string> grpList = new List<string>();
grpList.Add("length");
grpList.Add("Description");
var sourceParm = Expression.Parameter(typeof(Tracker), "x");
List<Expression> propertyExpressions = new List<Expression>();
foreach (var f in grpList.ToArray())
{
Expression conv = Expression.Convert(Expression.Property(sourceParm, f), typeof(object));
propertyExpressions.Add(conv);
}
var concatMethod = typeof(string).GetMethod(
"Concat",
new[] { typeof(object), typeof(object), typeof(object) });
Expression body = propertyExpressions.Aggregate((x, y) => Expression.Call(concatMethod,
x,
Expression.Constant(","),
y));
var groupSelector = Expression.Lambda<Func<Tracker, string>>(body, sourceParm);
var j = test.GroupBy(groupSelector.Compile());
}

Combine subitems from list of items

i want to ask you for help with combine all subitems from list, which looks like:
public class Subitem
{
public string Name { get; set; }
public string Code { get; set; }
public float Price { get; set; }
}
public class Item
{
public string Name { get; set; }
public string Code { get; set; }
public List<Subitem> Subitems { get; set; }
}
var components = new List<Item>();
components.Add(new Item()
{
Code = "ItemCode1",
Name = "Item1Name",
Subitems = new List<Subitem>
{
new Subitem { Code = "SubitemCode1", Price = 32 },
new Subitem { Code = "SubitemCode2", Price = 21 },
new Subitem { Code = "SubitemCode3", Price = 11 },
new Subitem { Code = "SubitemCode4", Price = 51 }
}
});
components.Add(new Item()
{
Code = "ItemCode2",
Name = "Item2Name",
Subitems = new List<Subitem>
{
new Subitem { Code = "SubitemCode5", Price = 11 },
new Subitem { Code = "SubitemCode6", Price = 22 },
new Subitem { Code = "SubitemCode7", Price = 52 },
new Subitem { Code = "SubitemCode8", Price = 63 }
}
});
components.Add(new Item()
{
Code = "ItemCode3",
Name = "Item3Name",
Subitems = new List<Subitem>
{
new Subitem { Code = "SubitemCode9", Price = 11 },
new Subitem { Code = "SubitemCode10", Price = 22 },
new Subitem { Code = "SubitemCode11", Price = 52 },
new Subitem { Code = "SubitemCode12", Price = 63 }
}
});
components.Add(new Item()
{
Code = "ItemCode4",
Name = "Item4Name",
Subitems = new List<Subitem>
{
new Subitem { Code = "SubitemCode13", Price = 11 },
new Subitem { Code = "SubitemCode14", Price = 22 },
new Subitem { Code = "SubitemCode15", Price = 52 },
new Subitem { Code = "SubitemCode16", Price = 63 }
}
});
I want to combine all subitems in model which looks like this:
new { Code = SubitemCode1, Price = 32 }
...
new { Code = SubitemCode8, Price = 63 }
new { Code = "SubitemCode1:SubitemCode5", Price = 43 } //11 + 32
...
new { Code = "SubitemCode1:SubitemCode8", Price = 95 } //32 + 63
new { Code = "SubitemCode2:SubitemCode5", Price = ... }
...
new { Code = "SubitemCode2:SubitemCode8", Price = ... }
#EDIT
new { Code = "SubitemCode1:SubitemCode5:SubitemCode9", Price = 54 } // 11 + 32 + 11
...
new { Code = "SubitemCode1:SubitemCode5:SubitemCode12", Price = 96 } // 11 + 32 + 63
new { Code = "SubitemCode1:SubitemCode6:SubitemCode9", Price = ... }
...
new { Code = "SubitemCode1:SubitemCode6:SubitemCode12", Price = ... }
...
new { Code = "SubitemCode1:SubitemCode8:SubitemCode9", Price = ... }
...
new { Code = "SubitemCode1:SubitemCode8:SubitemCode12", Price = ... }
new { Code = "SubitemCode2:SubitemCode5:SubitemCode9", Price = ... }
...
Can anyone explain to me how to get on with it? There could be 1-5 Item and 1-10 in Subitems in each Item and i need to have all combination of subitems with the addition of prices.
Subitems from Item in which they are, is not combinable, only Subitems from other Item
Thank You in Advance,
Best Regards.
You can simply make join over two different list like
var result = components[0].Subitems
.Join(components[1].Subitems, x => true, y => true, (a, b) => new { Code = a.Code + ":" + b.Code, Price = a.Price + b.Price })
.ToList();
OR you can do this by using linq
var result = from a in components[0].Subitems
from b in components[1].Subitems
select new
{
Code = a.Code + ":" + b.Code,
Price = a.Price + b.Price
};
And finally print the result
foreach (var item in result)
{
Console.WriteLine("Code: " + item.Code + "\t Price: " + item.Price);
}
Output:
Okay, i think that i got this.
The code looks like:
var result = new List<SubItem>(); //list of combined SubItems
var ms = 0; // start index of items from list to combine
var mk = 0; // end index of items from list to combine
for (int i = 0; i < components.Count; i++) // count of all items
{
if (i == 0) //if there is a first item then we don't combine codes and prices
{
for (int mat = 0; mat < components[i].SubItems.Count; mat++)
{
var data = components[i].SubItem[mat];
result.Add(new SubItem { Price = data.Price, Code = data.Code });
mk = mat; // set last index of SubItem to combine
}
continue;
}
for (int j = ms; j < mk + 1; j++) // iterate from first to last SubItem to combine them with new SubItems
{
for (int mat = 0; mat < components[i].SubItems.Count; mat++) // iterate through SubItems
{
result.Add(new SubItem { Code = result[j].Code + ":" + components[i].SubItem[mat].Code, price = result[j].Price + components[i].SubItem[mat].Price }); // Combine last SubItem with now iterating Subitem.
}
}
ms = mk + 1; // update new start index to combine
mk = result.Count - 1; // update new end index to combine
}
I achieved what I wanted. :)
Best Regards!

Find the matching postion and date in a List in c#

I have two Lists - StockData and UpDownData.
db1 newStock = new db1();
newStock.Date = (DateTime)reader["Date"];
newStock.High = (double)reader["High"];
StockData.Add(newStock);
db1 newStock2 = new db1();
newStock2.Date = (DateTime)reader2["Date"];
newStock2.Min_Max_Value = (double)reader2["Min_Max_Value"];
UpDownData.Add(newStock2);
int a = 0;
int pos = 0;
DateTime? date1 = null;
while (a < UpDownData.Count && UpDownData.ElementAt(a)?.Date == StockData[i].Date)
{
pos = a;
date1 = UpDownData.ElementAt(a).Date;
a++;
}
Console.WriteLine(date1);
I am trying to match the date in the StockData list with the date in the UpDownData list. After I find a match, I use the position (a) of the element in UpDownData list to print the matched date.
But the above code is NOT able to find the matching date. Can someone help?
Thanks
EDIT:
The below image should give you an idea :
Thus, the matched dates in UpDownData List are 6/30/2015 and 7/16/2015 at position a=0 and a=6 respectively. I only need the POSTION and DATES.
Try following :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ConsoleApplication65
{
class Program
{
static void Main(string[] args)
{
StockData.data = new List<StockData>() {
new StockData() { date = DateTime.Parse("6/17/2015"), high = 256.9},
new StockData() { date = DateTime.Parse("6/18/2015"), high = 260.7},
new StockData() { date = DateTime.Parse("6/23/2015"), high = 271.2},
new StockData() { date = DateTime.Parse("6/24/2015"), high = 267.9},
new StockData() { date = DateTime.Parse("6/25/2015"), high = 266},
new StockData() { date = DateTime.Parse("6/26/2015"), high = 266.9},
new StockData() { date = DateTime.Parse("6/30/2015"), high = 263.35},
new StockData() { date = DateTime.Parse("7/8/2015"), high = 271},
new StockData() { date = DateTime.Parse("7/10/2015"), high = 271},
new StockData() { date = DateTime.Parse("7/13/2015"), high = 274.35},
new StockData() { date = DateTime.Parse("7/14/2015"), high = 273.6},
new StockData() { date = DateTime.Parse("7/15/2015"), high = 271.7},
new StockData() { date = DateTime.Parse("7/16/2015"), high = 272.75}
};
UpDownData.data = new List<UpDownData>() {
new UpDownData() { date = DateTime.Parse("6/30/2015"), min_max = 263.35},
new UpDownData() { date = DateTime.Parse("7/8/2015"), min_max = 250},
new UpDownData() { date = DateTime.Parse("7/10/2015"), min_max = 236.65},
new UpDownData() { date = DateTime.Parse("7/13/2015"), min_max = 223.3},
new UpDownData() { date = DateTime.Parse("7/14/2015"), min_max = 209.95},
new UpDownData() { date = DateTime.Parse("7/15/2015"), min_max = 196.6},
new UpDownData() { date = DateTime.Parse("7/16/2015"), min_max = 272.75}
};
var results = (from sData in StockData.data
join uData in UpDownData.data on sData.date equals uData.date
select new { sData = sData, uData = uData })
.Where(x => x.sData.high == x.uData.min_max)
.Select(x => new { date = x.sData.date, value = x.sData.high }).ToList();
}
}
public class StockData
{
public static List<StockData> data = new List<StockData>();
public DateTime date { get; set; }
public double high { get; set; }
}
public class UpDownData
{
public static List<UpDownData> data = new List<UpDownData>();
public DateTime date { get; set; }
public double min_max { get; set; }
}
}

Find Average of a node in Multiple JSON strings

I have searched through many topics, find some relevant answers too, but I am still not able to reach to a solution, hence I am posting this question.
Problem Description
EmployeeResponse1 = [{"Ques":"1","Rating":"7"},{"Ques":"2","Rating":"1"},{"Ques":"3","Rating":"6"},{"Ques":"4","Rating":"1"},{"Ques":"5","Rating":"1"},{"Ques":"6","Rating":"1"},{"Ques":"7","Rating":"7"},{"Ques":"8","Rating":"1"},{"Ques":"9","Rating":"1"},{"Ques":"10","Rating":"1"},{"Ques":"11","Rating":"1"},{"Ques":"12","Rating":"1"},{"Ques":"13","Rating":"1"},{"Ques":"14","Rating":"1"},{"Ques":"15","Rating":"1"},{"Ques":"16","Rating":"10"}]
EmployeeResponse2 = [{"Ques":"1","Rating":"5"},{"Ques":"2","Rating":"4"},{"Ques":"3","Rating":"7"},{"Ques":"4","Rating":"8"},{"Ques":"5","Rating":"5"},{"Ques":"6","Rating":"9"},{"Ques":"7","Rating":"10"},{"Ques":"8","Rating":"4"},{"Ques":"9","Rating":"9"},{"Ques":"10","Rating":"6"},{"Ques":"11","Rating":"6"},{"Ques":"12","Rating":"6"},{"Ques":"13","Rating":"7"},{"Ques":"14","Rating":"7"},{"Ques":"15","Rating":"9"},{"Ques":"16","Rating":"8"}]
I have these two JSON strings in c# (there can be more).. Now I want to make a final JSON string which will be like:
EmployeeResponseAvg = [{"Ques":"1","Rating":"6"},{"Ques":"2","Rating":"2.5"},{"Ques":"3","Rating":"6.5"},{"Ques":"4","Rating":"4.5"},{"Ques":"5","Rating":"3"},{"Ques":"6","Rating":"5"},{"Ques":"7","Rating":"8.5"},{"Ques":"8","Rating":"2.5"},....,{"Ques":"16", "Rating": "9"}]
like I want rating of Ques = 1 should be the average of Rating (Ques = 1 of string 1) and Rating (Ques = 1 of string 2)... similarly for other questions
i.e like FINAL =[{ QUES = 1, RATING = (Emp1(Rating.WHERE(QUES = 1), Emp2(Rating.WHERE(QUES = 1),).AVERAGE),....................}]
Work So Far
MODEL -> SurveyResponse.cs
public class SurveyResponse
{
public string Ques { get; set; }
public string Rating { get; set; }
}
public class ResponseDataCalls
{
public static SurveyResponse PutData(string t, string v)
{
SurveyResponse s = new SurveyResponse();
s.Ques = t;
s.Rating = v;
return s;
}
}
WebAPI RevGroupChartController.cs
public class RevGroupChartController : ApiController
{
private hr_toolEntities _db = new hr_toolEntities();
public object Get(int cid, int gid)
{
spiderChart obj = new spiderChart();
var group_employees = (from ge in _db.hrt_group_employee
where ge.fk_group_id == gid
select ge.fk_employee_id).ToList();
List<string> EMP = new List<string>();
List<string> SUP = new List<string>();
List<SurveyResponse> EmpResponse = new List<SurveyResponse>();
List<SurveyResponse> SupResponse = new List<SurveyResponse>();
List<List<SurveyResponse>> tmpEMP = new List<List<SurveyResponse>>();
List<List<SurveyResponse>> tmpSUP = new List<List<SurveyResponse>>();
foreach(var emp in group_employees)
{
int eid = Convert.ToInt32(emp);
var Data = (from d in _db.hrt_cycle_response
join g in _db.hrt_cycle_groups on d.hrt_cycle.pk_cycle_id equals g.fk_cycle_id
where d.fk_cycle_id == cid && g.fk_group_id == gid && d.fk_employee_id == eid
select new
{
d.response_employee_answers,
d.response_supervisor_answers
}).First();
EMP.Add(Data.response_employee_answers);
SUP.Add(Data.response_supervisor_answers);
}
foreach(var e in EMP)
{
//tmpEMP = new JavaScriptSerializer().Deserialize<TEMP>(e);
var s = new JavaScriptSerializer();
List<SurveyResponse> em = s.Deserialize<List<SurveyResponse>>(e);
tmpEMP.Add(em);
}
foreach (var s in SUP)
{
//tmpSUP = new JavaScriptSerializer().Deserialize<TEMP>(s);
var e = new JavaScriptSerializer();
List<SurveyResponse> sp = e.Deserialize<List<SurveyResponse>>(s);
tmpSUP.Add(sp);
}
var empl = _db.hrt_questions.Select(x => new { x.question_name }).ToList();
List<int[]> Emprating = new List<int[]>();
//int avgRating;
int cnt = 0;
foreach(var item in tmpSUP)
{
int noofQ = item.Count;
int[] i = new int[noofQ];
for (int y = 0; y > tmpSUP.Count; y++)
{
i[y] = Convert.ToInt32(item[cnt].Rating);
}
Emprating.Add(i);
cnt++;
}
//obj.Employee = Data.response_employee_answers;
//obj.Supervisor = Data.response_supervisor_answers;
obj.ques = new List<object>();
for (int i = 0; i < empl.Count; i++)
{
obj.ques.Add(empl[i].question_name);
}
return obj;
}
public class TEMP
{
public List<SurveyResponse> data { get; set; }
}
}
Explanation of Code
I pass a cycle ID and a group ID...
Each group has more than 1 employee and each employee has a supervisor
so if say group ID 1023 has 2 employees.
Now we have 2 employees and 2 supervisors
we have a json record for each of them
LIKE DB TABLE RESPONSE {fk_emp_id, fk_sup_id, cycle_id, emp_reponse(json), supervisor_response(json)}
so I need to make ONE JSON string for employees (which contains the average of all ratings)
and ONE JSON string for SUPERVISOR (again, average of both the JSONs)
there could be any number of employees, depending on the group size
and each employee will always have a supervisor
In short I want a a string like:
FinalEmployeeResponse = [{'Ques': '1', 'Rating': 'R1'}, {'Ques': '2', 'Rating': 'R2'}, {'Ques': '3', 'Rating': 'R3'}, {'Ques': '4', 'Rating': 'R4'}, ........, {'Ques': '16', 'Rating': 'R16'}]
Here, R1 = AVERAGE(Emp1json.Rating.WHERE('Ques' = 1), Emp2json.Rating.WHERE('Ques' = 1), .....)
and
R2 = AVERAGE(Emp1json.Rating.WHERE('Ques' = 2), Emp2json.Rating.WHERE('Ques' = 2), .....)
... and so on....
Looking forward to your responses.
I am new on stack overflow, please ask for more details if I have missed something.
The correct way to do this is to parse this as JSON. The quick and dirty way is:
static void Main(string[] args)
{
string json1 = #"[{""Ques"":""1"",""Rating"":""7""},{""Ques"":""2"",""Rating"":""1""},{""Ques"":""3"",""Rating"":""6""},{""Ques"":""4"",""Rating"":""1""},{""Ques"":""5"",""Rating"":""1""},{""Ques"":""6"",""Rating"":""1""},{""Ques"":""7"",""Rating"":""7""},{""Ques"":""8"",""Rating"":""1""},{""Ques"":""9"",""Rating"":""1""},{""Ques"":""10"",""Rating"":""1""},{""Ques"":""11"",""Rating"":""1""},{""Ques"":""12"",""Rating"":""1""},{""Ques"":""13"",""Rating"":""1""},{""Ques"":""14"",""Rating"":""1""},{""Ques"":""15"",""Rating"":""1""},{""Ques"":""16"",""Rating"":""10""}]";
string json2 = #"[{""Ques"":""1"",""Rating"":""5""},{""Ques"":""2"",""Rating"":""4""},{""Ques"":""3"",""Rating"":""7""},{""Ques"":""4"",""Rating"":""8""},{""Ques"":""5"",""Rating"":""5""},{""Ques"":""6"",""Rating"":""9""},{""Ques"":""7"",""Rating"":""10""},{""Ques"":""8"",""Rating"":""4""},{""Ques"":""9"",""Rating"":""9""},{""Ques"":""10"",""Rating"":""6""},{""Ques"":""11"",""Rating"":""6""},{""Ques"":""12"",""Rating"":""6""},{""Ques"":""13"",""Rating"":""7""},{""Ques"":""14"",""Rating"":""7""},{""Ques"":""15"",""Rating"":""9""},{""Ques"":""16"",""Rating"":""8""}]";
string averages = AverageNodes(json1, json2);
Console.WriteLine(averages);
Console.ReadKey();
}
private static string AverageNodes(params string[] json)
{
var regex = new Regex(#"(""Ques"":""(?<question>\d+)"",""Rating"":""(?<rating>\d+)"")", RegexOptions.ExplicitCapture | RegexOptions.IgnoreCase);
var ANUs = regex.Matches(string.Join("", json))
.Cast<Match>()
.Select(m => new { Question = m.Groups["question"].Value, Rating = int.Parse(m.Groups["rating"].Value) })
.GroupBy(a => a.Question, a => a.Rating)
.Select(a => string.Format("{{\"Ques\":\"{0}\",\"Rating\":\"{1}\"}}", a.Key, a.Average()));
return "[" + string.Join(",", ANUs) + "]";
}
I found a 1 line answer to this using LINQ.
double _avg1 = tmpEMP.Select(x => Convert.ToInt32(x.ElementAt(i).Rating)).Average();

Compare members of a type - calculate the difference between members

I have the following type:
public class Parts
{
public string PartNo { get; set; }
public decimal Price { get; set; }
}
what I would like to do is to compare the price or each part with the cheapest one and display the difference in percentage.
This is what I have tried so far and it works:
var part1 = new Part {PartNo = "part1", Price = 10};
var part2 = new Part {PartNo = "part1", Price = 8};
var part3 = new Part {PartNo = "part1", Price = 12};
var parts = new List<Part> {part1, part2, part3};
var list = from p in parts
orderby p.Price ascending
select p;
var sb = new StringBuilder();
var counter = 0;
decimal firstPrice=0;
foreach (Part p in list)
{
if (counter == 0)
{
firstPrice = p.Price;
}
sb.Append(p.PartNo + ": " + p.Price + "," + ((p.Price/firstPrice)-1)*100 + Environment.NewLine);
counter++;
}
Console.WriteLine(sb.ToString(), "Parts List");
This outputs the following:
part1: 8, 0
part1: 10, 25.00
part1: 12, 50.0
This shows the price increase for each each part, and that is what I am trying to achieve but I was wondering is there a better way of calculating the price difference in percentage (e.g. with a LINQ query) or in any other way.
Thanks
I would calculate the difference as first step.
var cheapestPrice = parts.Min(p => p.Price);
var list = parts.Select(p => new {
Part = p,
DiffPercentage = ((p.Price - cheapestPrice) / cheapestPrice) * 100
});
foreach (var p in list)
Console.WriteLine("{0}: {1},{2}%", p.Part.PartNo, p.Part.Price, p.DiffPercentage);
// list defined as sorted by price ascending as per the code
var list = parts.OrderBy(p => p.Price); // less verbose way of saying the same
var firstPrice = list.First().Price;
var differences = list.Skip(1).Select(s => new {Part = s, PercentageDiff = (s.Price/firstPrice - 1)*100});
The .Skip(1) is optional. You may not want to compare cheapest price to itself.
Tim beat me to it, but use the select to create your string
void Main()
{
var part1 = new Part {PartNo = "part1", Price = 10};
var part2 = new Part {PartNo = "part1", Price = 8};
var part3 = new Part {PartNo = "part1", Price = 12};
var parts = new List<Part> {part1, part2, part3};
var lowest = parts.Min(p => p.Price );
var result = parts.Select (p => string.Format("Part #:{0} {1} -> {2}", p.PartNo, p.Price, ((p.Price/lowest)-1)*100 ));
result.ToList()
.ForEach(rs => Console.WriteLine (rs));
/*
Part #:part1 10 -> 25.00
Part #:part1 8 -> 0
Part #:part1 12 -> 50.0
*/
}
// Define other methods and classes here
public class Part
{
public string PartNo { get; set; }
public decimal Price { get; set; }
}

Categories

Resources