Show XML node value in MVC view by number of similar node? - c#

Is there anyway to group the xml node value by similar into number? I had tried to output the value as below but i can't get the out as what i want. Please guide me on this. Thanks!
My Answer_Data Sample in database: (After extract will get the C1 and C2)
Question_ID | Answer_Data
==============================================
1 | <Answer_Data><Answer>C1</Answer>
2 | <Answer_Data><Answer>C2</Answer>
3 | <Answer_Data><Answer>C2</Answer>
String[] data after extract using Linq:
["c1","c2","c2"]
Able to View in MVC:
c1
c2
c2
What i want is:
c1 - 1
c2 - 2
My Controller:
public ActionResult SURV_Answer_Result(int Survey_ID, string Language = "ENG")
{
List<AnswerQuestionViewModel> viewmodel = new List<AnswerQuestionViewModel>();
var query = from r in db.SURV_Question_Ext_Model
join s in db.SURV_Question_Model
on r.Qext_Question_ID equals
s.Question_ID
select new { r, s };
var viewModel = new AnswerQuestionViewModel();
viewModel.Survey_ID = Survey_ID;
string[] resultanswer = new string[queryResult.Count()];
foreach (var item in query.ToList())
{
string str = item.s.Answer_Data;
XElement qconfig;
qconfig = XElement.Parse(str);
string value = item.s.Question_Type;
int i = 0;
switch (value)
{
case "Choices":
{
XElement ChoicesType =
(from node in qconfig.Elements("ChoicesType")
select node).SingleOrDefault();
viewModel.ChoiceType = ChoicesType.Value;
XElement ChoicesAns =
Here is i get the answer data ===>> (from node in qconfig.Elements("Answer")
select node).SingleOrDefault();
resultanswer[i++] = ChoicesAns.Value;
viewModel.ResultAnswer = resultanswer;
}
break;
case "Multiple_Line":
{
// do nothing
}
break;
viewmodel.Add(new AnswerQuestionViewModel()
{
ResultAnswer = viewModel.ResultAnswer
});
}
return View(viewmodel);
}
}
My View:
if (Model[i].ChoiceType == "SingleChoice")
{
for (int x = 0; x < Model[i].ResultAnswer.Count(); x++)
{
#Html.LabelFor(m => m[i].Answer, Model[i].ResultAnswer[x].ToString(),new{ #class="qlabel2" })
<br/>
}
}

As you are stating in question that you are receiving array of element than you just try group by like this
string[] strarray = new string[] {"c1","c2","c2"};
var groups = from str in strarray
group str by str into g
select new {
key = g.Key,
count = g.Count()
}
try group by using linq like this
var xmlstr="<root><Answer_Data><Answer>C1</Answer></Answer_Data>
<Answer_Data><Answer>C2</Answer></Answer_Data>
<Answer_Data><Answer>C2</Answer></Answer_Data></root>";
XDocument xmldoc = XDocument.Parse(xmlstr);
var groups = from record in xmldoc.Descendants("Answer_Data")
group record by (string)record.Element("Answer")
into g
select new {
key = g.Key,
count = g.Count()
}

Related

How to group a datatable by month and count the rows that falls under that month

I'm trying to create a line chart using a datatable that has all the data that I need but I can't seem to group it successfully.
I need to group the datatable by month/year and count all the records that fall within each respective month/year.
I actually tried to extract the data and make the graph in excel. So it should look like this.
Ignore the quarters as those are auto generated by excel
Here's the code:
var chartResults = (from myrow in chartInstruction.Chart.AsEnumerable()
group myrow by new
{
series = myrow.Field<string>(chartInstruction.Series),
xaxis = myrow.Field<DateTime>(chartInstruction.Xaxis).ToShortDateString()
}
into g
select new
{
Field = g.Key,
Total = g.Count()
}).ToArray();
string[] xAxis = chartResults.Select(x => x.Field.xaxis).Distinct().OrderBy(x => x).ToArray();
string[] series = chartResults.Select(x => x.Field.series).Distinct().OrderBy(x => x).ToArray();
var seriesInfo = new List<SeriesInfo>();
foreach (string s in series)
{
var tmp = new List<double>();
foreach (string xx in xAxis)
{
var found = chartResults.FirstOrDefault(x => x.Field.xaxis == xx && x.Field.series == s);
tmp.Add(found?.Total ?? 0);
}
seriesInfo.Add(new SeriesInfo { Name = s, Series = tmp.ToArray() });
}

Retrurn list of objects matching by property

I have a method for parsing XML:
public static List<Profile> Parse XML(string Document)
{
List<Profile> Result = new List<Profile>();
doc = XDocument.Load(Document);
Resoults = (from n in doc.Descendants("level")
select new Profile()
{
CurrentID = int.Parse(n.Attribute("CurrentID").Value),
Location = (from l in n.Element("ID").Elements("ID")
select new Location()
{
id = (int)(l.Attribute("id")),
x = (Single)l.Attribute("x"),
y = (Single)l.Attribute("y"),
z = (Single)l.Attribute("z")
}).ToList(),
Bank = (from l in doc.Descendants("Banker")
select new Banker()
{
BankID = (int)(l.Attribute("id")),
BankX = (Single)(l.Attribute("x")),
BankY = (Single)(l.Attribute("y")),
BankZ = (Single)(l.Attribute("z"))
}).ToList(),
Vendor = (from l in doc.Descendants("Vendor")
select new Vendor()
{
VendorID = (int)(l.Attribute("id")),
VendorX = (Single)(l.Attribute("x")),
VendorY = (Single)(l.Attribute("y")),
VendorZ = (Single)(l.Attribute("z"))
}).ToList()
}).ToList();
var ProperID = Resoults.Where(s => s.CurrentID <= 10).Aggregate((c, d) => c.CurrentID > d.CurrentID ? c : d);
return ProperID; //error: Here i want to return list ProperID
}
I want to parse XML file and then get node out of parsed list with specific CurrentID.
I want to return ProperID list but compiler errores out with:
Cannot implicitly convert type 'Classes.XMLprofile.Profile' to 'System.Collections.Generic.List<Classes.XMLprofile.Profile>'
You want return Results that have proper id in CurrentId,
In code you got compiler error because of return value is a Profile object and method signature is a List of Profile objects, So:
return Resoults.Where(p=>p.CurrentID ==ProperID.CurrentID).ToList();

Remove Duplicate/Existing value from dropdownlist

I will like to generate a dropdownlist with unique value.
However i only able to generate an original dropdownlist which generated from database.
At my language table it contain 3 languages:
-ENG , GER, KOR
for the language i already used for a question list:
- KOR
So the result bind to dropdownlist should:
- ENG, GER
My Controller code:
List<SelectListItem> langResult = new List<SelectListItem>();
///// Ori Language
var result = from r in db.SURV_Language_Model
select r.Language;
///// Used Language
var result2 = from r in db.SURV_Question_Ext_Model
join s in db.SURV_Question_Model on r.Qext_Question_ID equals s.Question_ID
orderby s.Question_Position ascending
where r.Qext_Question_ID == Question_ID
select new { r, s };
/////Remaining Language
result 3 = result 2 - result 1 <==*** Pseudo code
foreach (var item in result3)
{
SelectListItem temp = new SelectListItem();
temp.Text = item;
temp.Value = item;
langResult.Add(temp);
}
ViewBag.LangList = langResult;
My View Code:
#Html.LabelFor(model => model.Language)
#Html.DropDownListFor(model => model.Language, ViewBag.LangList as IEnumerable<SelectListItem>)
#Html.ValidationMessageFor(model => model.Language, "*")
Anyway to perform this?
Was fixed by code below, hope can help you all:
List<SelectListItem> langResult = new List<SelectListItem>();
var result = from r in db.SURV_Language_Model
select r.Language;
var result2 = from r in db.SURV_Question_Ext_Model
join s in db.SURV_Question_Model on r.Qext_Question_ID equals s.Question_ID
orderby s.Question_Position ascending
where r.Qext_Question_ID == Question_ID
select r.Qext_Language;
List<string> list = new List<string>(result);
List<string> list2 = new List<string>(result2);
for (int x = 0; x < list.Count(); x++ )
{
if ( x < list2.Count())
{
if (list[0].ToString() == list2[x].ToString())
{
list.Remove(list[0].ToString());
}
}
}
foreach (var item in list)
{
SelectListItem temp = new SelectListItem();
temp.Text = item;
temp.Value = item;
langResult.Add(temp);
}
ViewBag.LangList = langResult;

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();

Tricky LINQ query for text file format transformation

I have a shopping list in a text file, like this:
BuyerId Item;
1; Item1;
1; Item2;
1; ItemN;
2; Item1;
2; ItemN;
3; ItemN;
I need to transform this list to a format like this:
Item1; Item2; Item3; ...; ItemN <--- For buyer 1
Item1; ...; ItemN <--- For buyer 2
Item1; ...; ItemN <--- For buyer 3
First I parse the CSV file like this:
IList<string[]> parsedcsv = (from line in lines.Skip(1)
let parsedLine = line.TrimEnd(';').Split(';')
select parsedLine).ToList();
Then I group the items with LINQ and aggregate them to the final format:
IEnumerable<string> buyers = from entry in parsedcsv
group entry by entry[0] into cart
select cart.SelectMany(c => c.Skip(1))
.Aggregate((item1, item2) =>
item1 + ";" + item2).Trim();
HOWEVER, as it happens, the BuyerId is not unique, but repeats after a number of times (for example, it can repeat like this: 1,2,3,4,5,1,2,3,4,5,1,2,3 or like this 1,2,3,1,2,3,1,2).
No big deal, I could quite easily fix this by grouping the items in a loop that checks that I only deal with one buyer at a time:
int lastBatchId = 0;
string currentId = parsedcsv[0][0];
for (int i = 0; i < parsedcsv.Count; i++)
{
bool last = parsedcsv.Count - 1 == i;
if (parsedcsv[i][0] != currentId || last)
{
IEnumerable<string> buyers = from entry in parsedcsv.Skip(lastBatchId)
.Take(i - lastBatchId + (last ? 1 : 0))
...
lastBatchId = i;
currentId = parsedcsv[i][0];
...
... however, this is not the most elegant solution. I'm almost certain this can be done only with LINQ.
Can anyone help me out here please ?
Thanks!
You should have a look at GroupAdjacent.
I'm not sure this is the best solution, but you said you want a pure Linq answer, so here you have it:
var result = from r in (
from l in lines.Skip(1)
let data = l.Split(new string[]{";"," "},
StringSplitOptions.RemoveEmptyEntries)
select new { Id = data.First(), Item = data.Skip(1).First() })
.Aggregate(new
{
Rows = Enumerable.Repeat(new
{
Id = string.Empty,
Items = new List<string>()
}, 1).ToList(),
LastID = new List<string>() { "" }
},
(acc, x) =>
{
if (acc.Rows[0].Id == string.Empty)
acc.Rows.Clear();
if (acc.LastID[0] != x.Id)
acc.Rows.Add(new
{
Id = x.Id,
Items = new List<string>()
});
acc.Rows.Last().Items.Add(x.Item);
acc.LastID[0] = x.Id;
return acc;
}
).Rows
select new
{
r.Id,
Items = string.Join(";", from x in r.Items
select x)
};
I wrote it pretty fast and it could be improved, I don't like it particularly because it resorts to a couple of tricks, but it's pure Linq and could be a starting point.

Categories

Resources