Seems like this is the kind of thing that would have already been answered but I'm unable to find it.
I have following table:
Id Parent Text
-----------------------
1 NULL A
2 1 B
3 2 C
4 3 D
5 NULL E
6 5 F
7 6 G
Now I want to have the result like this: (List<string>)
A
A > B
A > B > C
A > B > C > D
E
E > F
E > F > G
But the problem is that, this project that I am working on it, uses database first, I mean there's no navigation property, Parent is type of string not IEnumerable<T>.
What I have done so far:
var list = new List<string>();
string e2 = string.Empty;
foreach (var item in query)
{
string e1 = string.Empty;
if (item.Parent == null)
{
list.Add(p.Text);
e2 = item.Text;
}
else
{
foreach (var subItem in query.Where(t => t.Id == p.Parent))
{
if (subItem.Id != 1)
{
e1 = e2 + " > " + subItem.Text;
}
else
{
e1 = subItem.Text;
}
}
list.Add(e1 + " > " + p.Text);
}
}
Use recursive algorithm
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
namespace ConsoleApplication1
{
class Program
{
static List<string> list = new List<string>();
static DataTable dt = new DataTable();
static void Main(string[] args)
{
dt.Columns.Add("Id", typeof(int));
dt.Columns.Add("Parent", typeof(int));
dt.Columns["Parent"].AllowDBNull = true;
dt.Columns.Add("Text", typeof(string));
dt.Rows.Add(new object[] {1, null, "A"});
dt.Rows.Add(new object[] {2, 1, "B"});
dt.Rows.Add(new object[] {3, 2, "C"});
dt.Rows.Add(new object[] {4, 3, "D"});
dt.Rows.Add(new object[] {5, null, "E"});
dt.Rows.Add(new object[] {6, 5, "F"});
dt.Rows.Add(new object[] {7, 6, "G"});
GetRecursiveChildren(null, new List<string>());
foreach (string row in list)
{
Console.WriteLine(row);
}
Console.ReadLine();
}
static void GetRecursiveChildren(int? parent, List<string> parents)
{
foreach (DataRow row in dt.AsEnumerable().Where(x => x.Field<int?>("Parent") == parent))
{
string text = row.Field<string>("Text");
List<string> newParents = new List<string>();
newParents.AddRange(parents);
newParents.Add(text);
list.Add(string.Join(" > ",newParents));
int child = row.Field<int>("Id");
GetRecursiveChildren(child, newParents);
}
}
}
}
This works for me:
var source = new []
{
new { Id = 1, Parent = (int?)null, Text = "A" },
new { Id = 2, Parent = (int?)1, Text = "B" },
new { Id = 3, Parent = (int?)2, Text = "C" },
new { Id = 4, Parent = (int?)3, Text = "D" },
new { Id = 5, Parent = (int?)null, Text = "E" },
new { Id = 6, Parent = (int?)5, Text = "F" },
new { Id = 7, Parent = (int?)6, Text = "G" }
};
var lookup = source.ToLookup(x => x.Parent);
Func<int?, IEnumerable<string>> recurse = null;
recurse = p =>
lookup[p].SelectMany(x => new [] { x.Text }
.Concat(recurse(x.Id).Select(y => $"{x.Text} > {y}")));
foreach (string x in recurse(null))
{
Console.WriteLine(x);
}
I get:
A
A > B
A > B > C
A > B > C > D
E
E > F
E > F > G
Related
Here's a list, think of it as rows and columns where rows are going down and columns are side ways. the column count will always be the same for all rows.
var dataValues = new List<List<string>>()
{
//row 1
new List<string>(){"A","12","X","P8" },
//row 2
new List<string>(){"B","13","Y","P7" },
//row 3
new List<string>(){"C","12","Y","P6" },
//row 4
new List<string>(){"A","14","X","P5" },
//....
new List<string>(){"D","15","Z","P4" },
new List<string>(){"A","13","X","P3" },
new List<string>(){"B","14","Y","P2" },
new List<string>(){"C","13","Z","P1" },
};
The user providers a list of indexes to group by.
var userParam= new List<int>() { 0, 2 };
my question is how do i dynamically group dataValues by the userParam where user param is n amount of index. In the example above it will gorup by the first column and the 3rd. However the index can change and the amount of indexes can change aswell
example
var userParam2 = new List<int>() { 0, 2};
var userParam3 = new List<int>() { 0};
var userParam4 = new List<int>() { 0,1,2};
i know how to group by when i know how many indexes there will be (the the case below it's 2 index parameters), however when it's dynamic (x amount) then i do not know how to do this
var result = dataValues.GroupBy(e => new { G1 = e[userParam2 [0]], G2 = e[userParam2 [1]] });
You could use a Custom Comparer to achieve this :
1 - Declaration of GroupByComparer that inherit from IEqualityComparer :
public class GroupByComparer : IEqualityComparer<List<string>>
{
private static List<int> _intList;
public GroupByComparer(List<int> intList)
{
_intList = intList;
}
public bool Equals(List<string> x, List<string> y)
{
foreach (int item in _intList)
{
if (x[item] != y[item])
return false;
}
return true;
}
public int GetHashCode(List<string> obj)
{
int hashCode = 0;
foreach (int item in _intList)
{
hashCode ^= obj[item].GetHashCode() + item;
}
return hashCode;
}
}
2 - Call group by with EqualityComparer like :
var userParam = new List<int>() { 0, 2 };
var result = dataValues.GroupBy(e => e, new GroupByComparer(userParam));
I hope you find this helpful.
I believe i have something but this looks slow please let me know if there is anyway better of doing this.
var userParams = new List<int>() { 0, 2 };
var dataValues = new List<List<string>>()
{
new List<string>(){"A","12","X","P8" },
new List<string>(){"B","13","Y","P7" },
new List<string>(){"C","12","Y","P6" },
new List<string>(){"A","14","X","P5" },
new List<string>(){"D","15","Z","P4" },
new List<string>(){"A","13","X","P3" },
new List<string>(){"B","14","Y","P2" },
new List<string>(){"C","13","Z","P1" },
};
var result = new List<(List<string> Key, List<List<string>> Values)>();
result.Add((new List<string>(), dataValues));
for (int index = 0; index < userParams.Count; index++)
{
var currentResult = new List<(List<string> Key, List<List<string>> Values)>();
foreach (var item in result)
{
foreach (var newGroup in item.Values.GroupBy(e => e[userParams[index]]))
{
var newKey = item.Key.ToList();
newKey.Add(newGroup.Key);
currentResult.Add((newKey, newGroup.ToList()));
}
}
result = currentResult;
}
foreach(var res in result)
{
Console.WriteLine($"Key: {string.Join(#"\", res.Key)}, Values: {string.Join(" | ", res.Values.Select(e=> string.Join(",",e)))}");
}
final result
Key: A\X, Values: A,12,X,P8 | A,14,X,P5 | A,13,X,P3
Key: B\Y, Values: B,13,Y,P7 | B,14,Y,P2
Key: C\Y, Values: C,12,Y,P6
Key: C\Z, Values: C,13,Z,P1
Key: D\Z, Values: D,15,Z,P4
I have a list which I inserted on a database:
List<House> houses = new List<House> {
new House { Id = 1, Type = "A" },
new House { Id = 2, Type = "B" },
new House { Id = 3, Type = "C" }
new House { Id = 4, Type = "B" }
}
Using Linq to Entities I need to get Houses ordered by Type but it should be:
Houses of Type C
Houses of Type A
Houses of Type B
How to do this?
You can chain the ? : opeartor to create a custom sort like this:
var query = from h in context.Houses
orderby h.Type == "C" ? 0 : (h.Type == "A" ? 1 : 2)
select h;
Or method syntax
var query = context.Houses.OrderBy(h => h.Type == "C" ? 0 : (h.Type == "A" ? 1 : 2))
Sorry for late answer, but I would write an extension similar to this:
static void Main(string[] args)
{
var items = new[] { 1, 2, 3, 4, 5 }.AsQueryable();
//for example, revert entire list
var newOrder = new Dictionary<int, int>() { { 1, 5 }, { 2, 4 }, { 3, 3 }, { 4, 2 }, { 5, 1 } };
var sorted = items.OrderBy(newOrder.ToSwithExpression())).ToList();
foreach(var i in sorted)
{
Console.WriteLine(i);
}
Console.ReadKey();
}
static Expression<Func<T, K>> ToSwithExpression<T, K>(this Dictionary<T, K> dict, K defaultValue = default(K))
{
var paramm = Expression.Parameter(typeof(T), "x");
//If nothing maps - use default value.
Expression iter = Expression.Constant(defaultValue);
foreach (var kv in dict)
{
iter = Expression.Condition(Expression.Equal(paramm, Expression.Constant(kv.Key)), Expression.Constant(kv.Value, typeof(K)), iter);
}
return Expression.Lambda<Func<T, K>>(Expression.Convert(iter, typeof(K)), paramm);
}
As you see you can specify mapping switch instead of Dictionary. I used dictionary just because it is easier. EF will have no problem in chewing this one and transforming it into similar to other answers expression.
I have a list as below
PillarId Quarter Feature
1 Q12106 France
1 Q12016 Germany
1 Q22016 Italy
1 Q32016 Russia
2 Q22016 India
2 Q32016 USA
3 Q22016 China
3 Q32016 Australia
3 Q32016 New Zeland
3 Q42016 Japan
I want convert this into a list which looks like this
pillarId Q12016 Q22016 Q32016 Q42016
1 France Italy Russia
1 Germany
2 India USA
3 China Australia Japan
3 New Zeland
Can anybody suggest some sample code
Thanks
Try this
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
namespace ConsoleApplication16
{
class Program
{
static void Main(string[] args)
{
DataTable dt = new DataTable();
dt.Columns.Add("PillarId", typeof(int));
dt.Columns.Add("Quarter", typeof(string));
dt.Columns.Add("Feature", typeof(string));
dt.Rows.Add(new object[] {1, "Q12116", "France"});
dt.Rows.Add(new object[] {1, "Q12116", "Germany"});
dt.Rows.Add(new object[] {1, "Q22116", "Italy"});
dt.Rows.Add(new object[] {1, "Q32116", "Russia"});
dt.Rows.Add(new object[] {2, "Q22116", "India"});
dt.Rows.Add(new object[] {2, "Q32116", "USA"});
dt.Rows.Add(new object[] {3, "Q22116", "China"});
dt.Rows.Add(new object[] {3, "Q32116", "Austrailia"});
dt.Rows.Add(new object[] {3, "Q32116", "New Zeland"});
dt.Rows.Add(new object[] {3, "Q42116", "Japan"});
string[] uniqueQuarters = dt.AsEnumerable().Select(x => x.Field<string>("Quarter")).Distinct().ToArray();
var groups = dt.AsEnumerable()
.GroupBy(x => x.Field<int>("PillarId")).Select(x => x.GroupBy(y => y.Field<string>("Quarter")).Select(z => new { id = x.Key, quarter = z.Key, feature = z.Select((a,i) => new { feature = a.Field<string>("Feature"), index = i}).ToList()}).ToList()).ToList();
DataTable pivot = new DataTable();
pivot.Columns.Add("PillarId", typeof(int));
foreach (string quarter in uniqueQuarters)
{
pivot.Columns.Add(quarter, typeof(string));
}
foreach (var group in groups)
{
int maxNewRows = group.Select(x => x.feature.Count()).Max();
for (int index = 0; index < maxNewRows; index++)
{
DataRow newRow = pivot.Rows.Add();
foreach (var row in group)
{
newRow["PillarId"] = row.id;
newRow[row.quarter] = row.feature.Skip(index) == null || !row.feature.Skip(index).Any() ? "" : row.feature.Skip(index).First().feature;
}
}
}
}
}
}
This should work.
public struct temp
{
public int PillarID;
public string Quarter;
public string Feature;
}
static void Main(string[] args)
{
List<temp> list = new List<temp>
{
new temp {PillarID = 1, Quarter= "Q12106", Feature = "France"},
new temp {PillarID = 1, Quarter= "Q12106", Feature = "Germany"},
new temp {PillarID = 1, Quarter= "Q22016", Feature = "Italy"},
new temp {PillarID = 1, Quarter= "Q32016", Feature = "Russia"},
new temp {PillarID = 2, Quarter= "Q22016", Feature = "India"},
new temp {PillarID = 2, Quarter= "Q32016", Feature = "USA"},
new temp {PillarID = 3, Quarter= "Q22016", Feature = "China"},
new temp {PillarID = 3, Quarter= "Q32016", Feature = "Australia"},
new temp {PillarID = 3, Quarter= "Q32016", Feature = "New Zeland"},
new temp {PillarID = 3, Quarter= "Q42016", Feature = "Japan"}
};
IEnumerable<IGrouping<string, temp>> byQuarter = list.GroupBy(x => x.Quarter);
Console.WriteLine(byQuarter.ToString());
}
It does order them in the wanted way, but displaying it isn't so simple. I'm currently trying to make it display nicely
You can use dynamic keyword to create object as per your requirement at run time. I am not inserting multiple entries for a pillerId. In my case i am adding multiple features in quarter field for a given pillerId. Please look into below code for the same:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Dynamic;
namespace Test
{
public class Piller
{
public int PillarId;
public string Quarter;
public string Feature;
public static List<dynamic> Generate()
{
List<Piller> pillers = new List<Piller>();
pillers.Add(new Piller { PillarId = 1, Quarter = "Q12106", Feature = "France" });
pillers.Add(new Piller { PillarId = 1, Quarter = "Q12106", Feature = "Germany" });
pillers.Add(new Piller { PillarId = 1, Quarter = "Q22016", Feature = "Italy" });
pillers.Add(new Piller { PillarId = 1, Quarter = "Q32016", Feature = "Russia" });
pillers.Add(new Piller { PillarId = 2, Quarter = "Q22016", Feature = "Italy" });
pillers.Add(new Piller { PillarId = 2, Quarter = "Q32016", Feature = "USA" });
pillers.Add(new Piller { PillarId = 3, Quarter = "Q22016", Feature = "China" });
pillers.Add(new Piller { PillarId = 3, Quarter = "Q32016", Feature = "Australia" });
pillers.Add(new Piller { PillarId = 3, Quarter = "Q32016", Feature = "New Zeland" });
pillers.Add(new Piller { PillarId = 3, Quarter = "Q42016", Feature = "Japan" });
var pillerIds = (from p in pillers
select p.PillarId).Distinct();
var quarters = (from p in pillers
select p.Quarter).Distinct();
List<dynamic> transformedData = new List<dynamic>();
foreach (var pillerId in pillerIds)
{
var data = new ExpandoObject() as IDictionary<string, Object>;
data.Add("pillerId",pillerId);
foreach (var quarter in quarters)
{
var features = (from p in pillers
where p.PillarId == pillerId && p.Quarter == quarter
select p.Feature);
data.Add(quarter,features);
}
transformedData.Add(data);
}
return transformedData;
}
public static void Print(List<dynamic> data)
{
var dic = data[0] as IDictionary<string, Object>;
foreach (var field in dic.Keys)
{
Console.Write(field+" ");
}
Console.WriteLine();
foreach (dynamic record in data)
{
dic = record as IDictionary<string, Object>;
foreach (var field in dic.Keys)
{
if (field == "pillerId")
Console.Write(dic[field] + " ");
else
{
var value = dic[field];
if (value == null)
{
Console.Write(" ");
}
else
{
StringBuilder sb = new StringBuilder();
foreach (var item in (value as IEnumerable<string>))
{
if (sb.Length == 0)
sb.Append(item);
else
sb.Append(","+item);
}
Console.Write(sb.ToString());
}
}
Console.Write(" ");
}
Console.WriteLine();
}
}
}
}
My Table1 has some Header and Values:
KundeID KundeName Produkt Comment
1 Michael Jogurt "nichts"
2 Raj "Ich bin cool"
3 Gary Fanta "yahoo"
4 Miky Sprite
I want to change to Table2, make Values from Produkt as Header Columns:
KundeID KundeName Comment Jogurt Fanta Sprite
1 Michael "nichts" x
2 Raj "Ich bin cool"
3 Gary "yahoo" x
4 Miky x
My code for Table1:
DataTable table = new DataTable("Kunde");
table.Columns.Add("KundeID", typeof(Int32));
table.Columns.Add("KundeName", typeof(String));
table.Columns.Add("Produkt", typeof(String));
DataTable comment = new DataTable("Comment");
comment.Columns.Add("KundeName", typeof(String));
comment.Columns.Add("Comment", typeof(String));
DataSet ds = new DataSet("DataSet");
ds.Tables.Add(table);
ds.Tables.Add(comment);
object[] o1 = { 1, "Michael", "Jogurt" };
object[] o2 = { 2, "Raj" };
object[] o3 = { 3, "Gary", "Fanta" };
object[] o4 = { 4, "Miky", "Sprite" };
object[] c1 = { "Raj", "Ich bin cool" };
object[] c2 = { "Gary", "yahoo" };
object[] c3 = { "Michael", "nichts" };
table.Rows.Add(o1);
table.Rows.Add(o2);
table.Rows.Add(o3);
table.Rows.Add(o4);
comment.Rows.Add(c1);
comment.Rows.Add(c2);
comment.Rows.Add(c3);
var results = from table1 in table.AsEnumerable()
join table2 in comment.AsEnumerable()
on table1.Field<string>("KundeName") equals table2.Field<string>("KundeName") into prodGroup
from table4 in prodGroup.DefaultIfEmpty()
select new
{
KundeID = table1.Field<Int32?>("KundeID"),
KundeName = table1.Field<String>("KundeName"),
Produkt = table1.Field<String>("Produkt"),
Comment = table4 != null ? table4.Field<String>("Comment") : null,
};
dataGridView1.DataSource = results.ToList();
How can I take Value from "Produkt" and make it Header? thank you guys for helping
This should do the trick regardless of how many different products come up. It's pretty short and concise.
// build the new data table
var result = new DataTable();
result.Columns.Add("KundeID", typeof(Int32));
result.Columns.Add("KundeName", typeof(String));
result.Columns.Add("Comment", typeof(String));
result.Columns.AddRange(
(from c in
(from r in table.AsEnumerable()
where !r.IsNull("Produkt") && !string.IsNullOrEmpty(r.Field<string>("Produkt"))
select r.Field<string>("Produkt")).Distinct() // added DISTINCT
select new DataColumn(c, typeof(bool))).ToArray()
);
foreach (var r in results)
{
var productIndex = result.Columns.IndexOf(r.Produkt);
var vals = new List<object>() { r.KundeID, r.KundeName, r.Comment };
for (int i = 3; i < result.Columns.Count; i++)
{
if (i == productIndex)
{
vals.Add(true);
}
else
{
vals.Add(false);
}
}
result.LoadDataRow(vals.ToArray(), true);
}
var products = table.AsEnumerable()
.GroupBy(c => c["Produkt"])
.Where(g => !(g.Key is DBNull))
.Select(g => (string)g.Key)
.ToList();
var newtable = table.Copy();
products.ForEach(p=>newtable.Columns.Add(p,typeof(bool)));
foreach (var row in newtable.AsEnumerable())
{
if (!(row["Produkt"] is DBNull)) row[(string)row["Produkt"]] = true;
}
newtable.Columns.Remove("Produkt");
Try following...this may help you....
DataTable table = new DataTable("Kunde");
table.Columns.Add("KundeID", typeof(Int32));
table.Columns.Add("KundeName", typeof(String));
table.Columns.Add("Produkt", typeof(String));
table.Columns.Add("Comment", typeof(String));
object[] o1 = { 1, "Michael", "Jogurt", "nichts" };
object[] o2 = { 2, "Raj","","Ich bin cool" };
object[] o3 = { 3, "Gary", "Fanta","yahoo" };
object[] o4 = { 4, "Miky", "Sprite","" };
table.Rows.Add(o1);
table.Rows.Add(o2);
table.Rows.Add(o3);
table.Rows.Add(o4);
Dictionary<int,string> dictObj=new Dictionary<int, string>();
for (int i = 0; i < table.Rows.Count; i++)
{
dictObj.Add(Convert.ToInt32(table.Rows[i][0].ToString()), table.Rows[i][2].ToString());
}
foreach (var obj in dictObj)
{
if (string.IsNullOrEmpty(obj.Value))
{
table.Columns.Add(obj.Value, typeof(String));
DataRow row = table.Rows[obj.Key];
row[obj.Value] = "X";
}
}
Given this example data (in .NET classes where Po, Sku, Qty are properties):
PO, Sku, Qty
1,ABC,1
1,DEF,2
1,GHI,1
1,QWE,1
1,ASD,1
1,ZXC,5
1,ERT,1
2,QWE,1
2,ASD,11
2,ZXC,1
3,ERT,1
3,DFG,1
3,DFH,1
3,CVB,4
3,VBN,1
3,NMY,1
I need to transform it into a fixed column format, with a max of 5 SKUs per line (repeating the PO if needed for > 5):
PO, SkuA, QtyA, SkuB, QtyB, SkuC, QtyC, SkuD, QtyD, SkuE, QtyE
1, ABC, 1, DEF, 2, GHI, 1, QWE, 1, ASD, 1
1, ZXC, 5, ERT, 1, , , , , ,
2, QWE, 1, ASD, 11, ZXC, 1, , , ,
3, ERT, 1, DFG, 1, DFH, 1, CVB, 4, VBN, 1
3, NMY, 1, , , , , , , ,
Output can be CSV (which is what I'm outputting), or .NET classes - no matter there. Is there a simple way to do this in Linq by grouping by PO, then by counts of 5?
EDIT: I have no control of over the destination format. And for anyone interested, it's VendorNet and VendorBridge that require this nonsense.
Firstly, here's the query that will generate the correct hierarchy of objects. I'm using anonymous types but it's easy enough to change it to use your own proper classes.
var query = yourData
.GroupBy
(
x => x.PO
)
.SelectMany
(
x => x.Select
(
(y, i) => new { y.PO, y.Sku, y.Qty, Key = i / 5 }
)
)
.GroupBy
(
x => new { x.PO, x.Key }
);
Using LINQ to create the CSV from the query results is bit of a hack, but it gets the job done. (The "benefit" of using LINQ is that you could chain the original query and the CSV generation into a single, massive statement, should you wish.)
IEnumerable<string> csvLines = query
.Select
(
x => x.Aggregate
(
new { Count = 0, SB = new StringBuilder() },
(a, y) => new
{
Count = a.Count + 1,
SB = ((a.SB.Length == 0) ? a.SB.Append(y.PO) : a.SB)
.Append(", ").Append(y.Sku).Append(", ").Append(y.Qty)
},
a => a.SB.ToString() + string.Join(", , ", new string[6 - a.Count])
)
);
string csv = string.Join(Environment.NewLine, csvLines.ToArray());
In my opinion, creating the CSV without using LINQ makes the code much more readable:
StringBuilder sb = new StringBuilder();
foreach (var group in query)
{
int count = 0;
foreach (var item in group)
{
if (count++ == 0)
{
sb.Append(item.PO);
}
sb.Append(", ").Append(item.Sku).Append(", ").Append(item.Qty);
}
while (count++ < 5)
{
sb.Append(", , ");
}
sb.Append(Environment.NewLine);
}
string csv = sb.ToString();
Here you go. I didn't format the output the way you wanted. But this should give you an idea of how to pivot rows. Hope this helps :-)
public class MyClass
{
public int PO { get; set; }
public String SKU { get; set; }
public int Qty { get; set; }
public static IEnumerable<MyClass> GetList()
{
return new List<MyClass>()
{
new MyClass {PO = 1, SKU = "ABC", Qty = 1},
new MyClass {PO = 1, SKU = "DEF", Qty = 2},
new MyClass {PO = 1, SKU = "GHI", Qty = 1},
new MyClass {PO = 1, SKU = "QWE", Qty = 1},
new MyClass {PO = 1, SKU = "ASD", Qty = 1},
new MyClass {PO = 1, SKU = "ZXC", Qty = 5},
new MyClass {PO = 1, SKU = "ERT", Qty = 1},
new MyClass {PO = 2, SKU = "QWE", Qty = 1},
new MyClass {PO = 2, SKU = "ASD", Qty = 1},
new MyClass {PO = 2, SKU = "ZXC", Qty = 5},
};
}
}
EDIT: I've fixed the query based on Luke's comment
var lQuery =
MyClass.GetList()
.GroupBy(pArg => pArg.PO)
.Select(pArg => new
{
Test = pArg.Select((pArg1, pId) =>
new {ID = (pId / 5),
pArg1.PO, pArg1.SKU, pArg1.Qty})
.GroupBy(pArg1 => pArg1.ID)
.Select(pArg1 =>
pArg1.Aggregate(pArg.Key.ToString(),
(pSeed, pCur) =>
pSeed + pCur.SKU + ","))
});