I'm trying to dynamically load my datatable with an ASP.NET a web-method written in C#. The method seems to work well but nothing I try gets the datatable to respond properly.
Here's my code:
var oTable = $('table.datatable').dataTable({
"processing": true,
"serverSide": true,
"ajax": {
"url": "SearchForCustomers.aspx/GetUsers",
"type": "POST",
"contentType": "application/json; charset=utf-8",
"dataType": "json"
},
"columns": [{
"data": "A"
}, {
"data": "B"
}, {
"data": "C"
}, {
"data": "D"
}, {
"data": "E"
}, {
"data": "F"
}]
});
My ASP.NET web-method:
public class AA
{
public string A { get; set; }
public string B { get; set; }
public string C { get; set; }
public string D { get; set; }
public string E { get; set; }
public string F { get; set; }
}
[WebMethod]
public static string GetUsers()
{
/*List<UserAccount> listOfUserAccounts = UserAccount.GetUserAccounts(ApplicationConfiguration.ORDER_TYPES.DESC);
JavaScriptSerializer jSearializer = new JavaScriptSerializer();
return jSearializer.Serialize(listOfUserAccounts);*/
List<AA> list = new List<AA>();
list.Add(new AA { A = "a", B = "b", C = "c", D = "d", E = "e", F = "f" });
list.Add(new AA { A = "a", B = "b", C = "c", D = "d", E = "e", F = "f" });
list.Add(new AA { A = "a", B = "b", C = "c", D = "d", E = "e", F = "f" });
list.Add(new AA { A = "a", B = "b", C = "c", D = "d", E = "e", F = "f" });
list.Add(new AA { A = "a", B = "b", C = "c", D = "d", E = "e", F = "f" });
list.Add(new AA { A = "a", B = "b", C = "c", D = "d", E = "e", F = "f" });
list.Add(new AA { A = "a", B = "b", C = "c", D = "d", E = "e", F = "f" });
JavaScriptSerializer jSearializer = new JavaScriptSerializer();
return jSearializer.Serialize(list);
}
The AA class was made up in order to test the functionally of the datatable. The datatable receives no rows at all.
Thanks in advance.
Why it is not working with webmethod
Because, when Jquery datable makes a post request, it does send some parameter to post method, in this case it is GetUsers. But since there is no input parameter for this function, it shows ajax error internal error 500 . Error message is - Invalid JSON primitive , if you search this, it says, if there is mismatch between jquery supplied param in post and webmethod ( in this case it is so), then this error occurs. I know, this input parameter is not required at binding time, but still datatable ajax sends that for binding time, and those parameter are helpful for sorting, paging etc. Following is the screenshot,that shows POST params.
How to solve this
Move those methods to ashx hanlder, this way parameter ( such as sorting, searching etc..) will be captured by context.Request.Form ( this might not be required at binding time - this is your case).
But still, you need to modify supplied code, you need to wrap List<AA> to data and also include totalRecord, else jquery datatable shows error. Following is the code that i have tried and it is working.
public void ProcessRequest(HttpContext context)
{
context.Response.ContentType = "application/json";
List<AA> list = new List<AA>();
list.Add(new AA { A = "a", B = "b", C = "c", D = "d", E = "e", F = "f" });
list.Add(new AA { A = "a", B = "b", C = "c", D = "d", E = "e", F = "f" });
list.Add(new AA { A = "a", B = "b", C = "c", D = "d", E = "e", F = "f" });
list.Add(new AA { A = "a", B = "b", C = "c", D = "d", E = "e", F = "f" });
list.Add(new AA { A = "a", B = "b", C = "c", D = "d", E = "e", F = "f" });
list.Add(new AA { A = "a", B = "b", C = "c", D = "d", E = "e", F = "f" });
list.Add(new AA { A = "a", B = "b", C = "c", D = "d", E = "e", F = "f" });
JavaScriptSerializer jSearializer = new JavaScriptSerializer();
var result = new { data = list, recordsTotal = 8 };
context.Response.Write(jSearializer.Serialize(result));
}
Related
If I have the following sublists, how can I remove 'duplicates' so that I only have L1, L2 and L3 remaining? I don't mind which variant remains, as long as the duplicates are gone.
List<List<string>> mylist = new List<List<string>>();
List<string> L1 = new List<string> { "a", "b", "c" };
List<string> L2 = new List<string> { "d", "e", "f" };
List<string> L3 = new List<string> { "g", "h", "i" };
List<string> L4 = new List<string> { "c", "a", "b" };
List<string> L5 = new List<string> { "a", "c", "b" };
List<string> L6 = new List<string> { "f", "d", "e" };
It's worth mentioning that I'm removing the duplicates to improve performance in another part of my program, so anything too intensive would not be appropriate. Thanks!
you can use Linq by applying Distinct function with a custom comparer like the following code:
1 - Create Custom generic comparer for List<T>:
public class GenericComparer<T> : IEqualityComparer<List<T>>
{
public bool Equals(List<T> x, List<T> y)
{
return x.Count == y.Count && x.All(xx => y.Contains(xx));
}
public int GetHashCode(List<T> obj)
{
int hashCode = 0;
foreach(T str in obj)
{
hashCode ^= str.GetHashCode();
}
return hashCode;
}
}
2 - call Distinct function with StringListComparer like :
List<List<string>> mylist = new List<List<string>>()
{
new List<string> { "a", "b", "c" },
new List<string> { "d", "e", "f" },
new List<string> { "g", "h", "i" },
new List<string> { "c", "a", "b" },
new List<string> { "a", "c", "b" },
new List<string> { "f", "d", "e" },
};
var result = mylist.Distinct(new GenericComparer<string>()).ToList();
3 - Demo
foreach(List<string> strList in result)
{
Console.WriteLine(string.Join(",", strList));
}
4- Result
a,b,c
d,e,f
g,h,i
If you have a list of integer, you can call Distinct method like :
var result1 = mylist1.Distinct(new GenericComparer<int>()).ToList();
I hope this help you out.
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 4 years ago.
Improve this question
I am trying to solve this problem:
I have multiple array of string with some having duplicate items. I need to come up with a final list that has most items in each list
a1 = Array{"A", "B", "C","D","E","F"};
a2 = Array{"A", "B", "B", "C","D","D","D","E","F"};
a3 = Array{"A", "B", "B", "C","D","D","E","F"};
a4 = Array{"A", "B", "B", "B", "C","D","D","E","F"};
a5 = Array{"A", "B", "B", ","D","D","E","E","F"};
Final result should be:
FinalArray = {"A", "B", "B", "B", "C","D","D","D","E","E""F"};
Max. occurrence each items accounted in the final result.
How can I achieve this?
One simple way to solve do this is to first create a list to store the results, and then iterate through the unique items in each array, and add the difference between the count of items in the current array with the count of items in the results (if it's a positive number).
For example:
var arrays = new[]
{
new[] {"A", "B", "C", "D", "E", "F"},
new[] {"A", "B", "B", "C", "D", "D", "D", "E", "F"},
new[] {"A", "B", "B", "C", "D", "D", "E", "F"},
new[] {"A", "B", "B", "B", "C", "D", "D", "E", "F"},
new[] {"A", "B", "B", "C", "D", "E", "E", "F"},
};
var result = new List<string>();
foreach (var array in arrays)
{
var distinctItems = array.Distinct();
foreach (var distinctItem in distinctItems)
{
var diff = array.Count(i => i == distinctItem) -
result.Count(i => i == distinctItem);
if (diff > 0) result.AddRange(Enumerable.Repeat(distinctItem, diff));
}
}
Console.WriteLine(string.Join(", ", result.OrderBy(i => i)));
Output
Simple.
var arrays = new[]
{
new[] {"A", "B", "C", "D", "E", "F"},
new[] {"A", "B", "B", "C", "D", "D", "D", "E", "F"},
new[] {"A", "B", "B", "C", "D", "D", "E", "F"},
new[] {"A", "B", "B", "B", "C", "D", "D", "E", "F"},
new[] {"A", "B", "B", "C", "D", "E", "E", "F"},
};
var result =
arrays
.SelectMany(xs => xs.GroupBy(x => x).Select(x => new { x.Key, Count = x.Count() }))
.GroupBy(x => x.Key, x => x.Count)
.Select(x => new { x.Key, Count = x.Max() })
.SelectMany(x => Enumerable.Repeat(x.Key, x.Count))
.ToArray();
That gives: A, B, B, B, C, D, D, D, E, E, F
Sounds like a homework problem so I'm not sure if you're supposed to use specific methods/logic to solve it but I'll describe how I'd solve it.
Break down the problem. The requirement (as I understand it) is to display each value the max number of times it appears in any one set. The first step would be to count how many times each value appears in each set, which can be accomplished using ‘GroupBy’ then the ‘Count’ aggregate:
aN.GroupBy( v => v )
.Select( g => new
{
Value = g.Key,
Count = g.Count(),
} );
Similarly, we would then combine the results into a single set and group them by value to obtain the ‘Max’ Count value for use in producing the result set:
combinedResults.GroupBy( at => at.Value )
.Select( g => new
{
Value = g.Key,
Count = g.Max( at => at.Count ),
} );
Before we continue, let's combine the first two steps, but even before that, let's combine the arrays into their own set of sets.
var sets = new List<IEnumerable<string>>
{
new string[]{ "A", "B", "C", "D", "E", "F" },
new string[]{ "A", "B", "B", "C", "D", "D", "D", "E", "F" },
... etc ...
};
var valueMaxCounts = sets
.Select( s =>
s.GroupBy( v => v )
.Select( g => new
{
Value = g.Key,
Count = g.Count(),
} ) )
.GroupBy( at => at.Value )
.Select( g => new
{
Value = g.Key,
Count = g.Max( at => at.Count ),
} );
So now we have a set of Values with the max number of times each value appeared in one of the input sets. We now want to iterate through the results and add each value Count times.
var resultList = new List<string>();
foreach( var vmc in valueMaxCounts )
{
//for( var i = 0; i < vmc.Count; ++I )
//{
// resultList.Add( vmc.Value );
//}
resultList.AddRange( Enumerable.Repeat( vmc.Value, vmc.Count ) );
}
The final Select of the query and loop can be replaced with a call to SelectMany:
...query up to .GroupBy( at => at.Value )...
.SelectMany( g => Enumerable.Repeat( g.Key, g.Max( at => at.Count ) ) )
How do I create a method setOutput() that calculates and sets the max output of each item (a,b,c,d) in Formula by multiplying the percentage in Formula to the amt in Item through its common id? I think I worked out the logic but I don't know how to use the id to reference values for calculation.
I.e. how do I reference values by their id within arrays in a nested foreach loop?
Class Item {
public string id { get;set }
public double? amt { get;set } }
Class Formula {
public string id { get;set }
public double? percent { get;set }
public double? output { get;set } }
Item[] inventory = {
new Item { id = "a", amt = 111.1},
new Item { id = "b", amt = 222.2},
new Item { id = "c", amt = 333.3,
new Item { id = "d", amt = 400.4} }
Formula[] formulas = { new Formula {
{id = "a", percent=25.0, output = null},
{id = "b", percent=25.0, output = null},
{id = "c", percent=25.0, output = null},
{id = "d", percent=25.0, output = null}; },
new Formula {
{id = "a", percent=20.0, output = null};
{id = "b", percent=20.0, output = null};
{id = "c", percent=60.0, output = null};
{id = "d", percent= 0.0, output = null}; },
new Formula {
{id = "a", percent=30.0, output = null};
{id = "b", percent=30.0, output = null};
{id = "c", percent=20.0, output = null};
{id = "d", percent=20.0} output = null}; } }
setOutput(Item[] inventory, Formula[] formulas)
{
// Loop through each Formula in formulas
// Loop through each Item in
// Item.amt * Formula.percentage/100 = Formula.amt
foreach (var Formula in formulas) //
{
foreach (Item item in Raw)
{
(id="a") Raw.amt* Formula.percent/100 = Formula.output
(id="b") Raw.amt* Formula.percent/100 = Formula.output
(id="c") Raw.amt* Formula.percent/100 = Formula.output
(id="d") Raw.amt* Formula.percent/100 = Formula.output
}
}
}
Hi assuming if your Item array has Items with unique id's something like below in your code
Item[] inventory = {new Item { id = "a", amt = 111.1},
new Item { id = "b", amt = 222.2},
new Item { id = "c", amt = 333.3 },
new Item { id = "d", amt = 400.4} };
Formula[] formulas = { new Formula {id = "a", percent=25.0, output = null} ,
new Formula {id = "b", percent=25.0, output = null} ,
new Formula {id = "c", percent=25.0, output = null},
new Formula {id = "d", percent=25.0, output = null} };
Then in your setouput function you could do something like below to set your output property in formulas array
formulas.ToList().ForEach(var => var.output = var.percent * inventory.First(var1 => var1.id == var.id).amt / 100);
A better approach is to make formulas data type from Formula[] to List
Assuming you meant for your formulas to be List<Formula>[] so you could have lists of Formulas, converting the inventory of Items to a Dictionary makes it easy:
void setOutput(Item[] inventory, List<Formula>[] formulas) {
var Raw = inventory.ToDictionary(i => i.id, i => i.amt);
foreach (var FormulaSet in formulas)
foreach (var formula in FormulaSet)
formula.output = Raw[formula.id] * formula.percent / 100;
}
I have two lists of string:
List<string> tmpCols = new List<string>();
List<string> tmpRows = new List<string>();
e.g. tmpCols = [A,B,C]; and tmpRows = [X, Y];
I need to iterate both list and get a Json result like this:
new matrix() { id = "1", col = "A", row = "X" });
new matrix() { id = "2", col = "B", row = "X" });
new matrix() { id = "3", col = "C", row = "X" });
new matrix() { id = "4", col = "A", row = "Y" });
new matrix() { id = "5", col = "B", row = "Y" });
new matrix() { id = "6", col = "C", row = "Y" });
The dimension in this case would be 2 rows and 3 columns.
This is a textbook example of a nested loop. Loops can contain other loops, where the inner one repeats for each element of the outer one. This one might look something like:
var result = new List<matrix>();
var count = 1;
foreach (var r in tmpRows)
foreach (var c in tmpCols)
result.Add(new matrix { id = (count++).ToString(), col = c, row = r });
I think this is a late answer
need to iterate both list and get a Json result like this:
It is not a json, I guess you want something like this
List<string> tmpCols = new List<string>() { "A", "B", "C" };
List<string> tmpRows = new List<string>() { "X", "Y" };
var query = tmpCols.SelectMany(c => tmpRows.Select(r => new {id=index++, col=c, row = r }));
var json = JsonConvert.SerializeObject(query, Newtonsoft.Json.Formatting.Indented);
Console.WriteLine(json);
OUTPUT:
[
{
"id": 6,
"col": "A",
"row": "X"
},
{
"id": 7,
"col": "A",
"row": "Y"
},
{
"id": 8,
"col": "B",
"row": "X"
},
{
"id": 9,
"col": "B",
"row": "Y"
},
{
"id": 10,
"col": "C",
"row": "X"
},
{
"id": 11,
"col": "C",
"row": "Y"
}
]
Solved using this code:
var tmpMatrix = new List<matrix>();
for (int k = 0; k < tmpRows.Count; k++)
{
for (int j = 0; j < tmpCols.Count; j++)
{
int ident = k*tmpCols.Count + j;
tmpMatrix.Add(new matrix() { id = ident.ToString(), col = tmpCols[j], row = tmpRows[k] });
}
}
I have a generic list such as below,
var steps = new List<Step>
{
new Step { From = "A", To = "D", Quantity = 0 },
new Step { From = "D", To = "J", Quantity = 0 },
new Step { From = "J", To = "T", Quantity = 0 },
new Step { From = "D", To = "K", Quantity = 0 },
new Step { From = "K", To = "T", Quantity = 0 },
new Step { From = "E", To = "K", Quantity = 0 },
new Step { From = "A", To = "E", Quantity = 0 },
new Step { From = "B", To = "E", Quantity = 0 },
new Step { From = "E", To = "L", Quantity = 5 },
new Step { From = "B", To = "F", Quantity = 5 },
new Step { From = "B", To = "G", Quantity = 5 },
new Step { From = "F", To = "I", Quantity = 5 },
new Step { From = "G", To = "I", Quantity = 5 },
new Step { From = "C", To = "H", Quantity = 0 },
new Step { From = "H", To = "Z", Quantity = 0 },
new Step { From = "H", To = "Y", Quantity = 0 },
new Step { From = "H", To = "X", Quantity = 5 },
new Step { From = "X", To = "I", Quantity = 5 },
new Step { From = "I", To = "V", Quantity = 5 },
new Step { From = "L", To = "V", Quantity = 5 },
new Step { From = "Y", To = "V", Quantity = 5 },
new Step { From = "Y", To = "M", Quantity = 0 },
new Step { From = "Z", To = "M", Quantity = 0 },
new Step { From = "Z", To = "N", Quantity = 0 },
new Step { From = "M", To = "O", Quantity = 0 },
};
I would like to remove items from the list. It will start first item of the list. It will remove items until next quantity of item is greater then zero.
It should do the same job reverse.
It is like string.Trim('0').
My result should be like below :
var steps = new List<Step>
{
new Step { From = "E", To = "L", Quantity = 5 },
new Step { From = "B", To = "F", Quantity = 5 },
new Step { From = "B", To = "G", Quantity = 5 },
new Step { From = "F", To = "I", Quantity = 5 },
new Step { From = "G", To = "I", Quantity = 5 },
new Step { From = "C", To = "H", Quantity = 0 },
new Step { From = "H", To = "Z", Quantity = 0 },
new Step { From = "H", To = "Y", Quantity = 0 },
new Step { From = "H", To = "X", Quantity = 5 },
new Step { From = "X", To = "I", Quantity = 5 },
new Step { From = "I", To = "V", Quantity = 5 },
new Step { From = "L", To = "V", Quantity = 5 },
new Step { From = "Y", To = "V", Quantity = 5 },
};
You want something like this:
steps = steps.SkipWhile(s => s.Quantity == 0).Reverse()
.SkipWhile(s => s.Quantity == 0).Reverse()
.ToList();
This would be the "simple" solution I guess.
It would be faster to search for the bounds of the desired range of steps first and then get that using GetRange.
I think, the best option is reassign step to new list
list = list.SkipWhile(s => s.Quantity == 0).ToList();
UPD: Yeah, my fault, I made TrimStart only. Was inattention.
This should do the trick:
steps = steps
.SkipWhile(step => step.Quantity == 0)
.TakeWhile((step, index) =>
steps.Skip(index).Any(nextSteps => nextSteps.Quantity != 0))
.ToList();
The SkipWhile first skips all steps with quantity=0, then it takes all steps so long as there are following steps with a quantity != 0.
Whilst the simple solution would be to revere the list twice that could get expensive for large lists.
list = list.SkipWhile(s => s.Quantity == 0).Reverse()
.SkipWhile( s => s.Quantity == 0).Reverse().ToList();
A more efficient solution would be to define an extension method like this:
public static IEnumerable TrimLast(IEnumerable<T> this, Func<T, Bool> cond) {
foreach (var item in this) {
if (!cond(item)) {
foreach (var storeditem in store) {
yield return storeditem;
}
store.Clear;
yield return item;
} else {
store.Add(item);
}
}
}
then call it: list = list.SkipWhile(s => s.Quantity == 0).TrimLast(s => s.Quantity == 0).ToList();
This has the advantage of never storing more than the longest consecutive sequence of zeros unlike the reverse solution which needs to store the whole list twice.