Reputation: 1887
I have a string like this -
var roleDetails = "09A880C2-8732-408C-BA09-4AD6F0A65CE9^Z:WB:SELECT_DOWNLOAD:0000^Product Delivery - Download^1,24B11B23-1669-403F-A24D-74CE72DFD42A^Z:WB:TRAINING_SUBSCRIBER:0000^Training Subscriber^1,6A4A6543-DB9F-46F2-B3C9-62D69D28A0B6^Z:WB:LIC_MGR_HOME_REDL:0000^License Manager - Home use^1,76B3B165-0BB4-4E3E-B61F-0C0292342CE2^Account Admin^Account Admin^1,B3C0CE51-00EE-4A0A-B208-98653E21AE11^Z:WB:1BENTLEY_ISA_ADMIN:0000^Co-Administrator^1,CBA225BC-680C-4627-A4F6-BED401682816^ReadOnly^ReadOnly^1,D80CF5CF-CB6E-4424-9D8F-E29F96EBD4C9^Z:WB:MY_SELECT_CD:0000^Product Delivery - DVD^1,E0275936-FBBB-4775-97D3-9A7D19D3E1B4^Z:WB:LICENSE_MANAGER:0000^License Manager^1";
Spliting it with "," returns this -
[0] "09A880C2-8732-408C-BA09-4AD6F0A65CE9^Z:WB:SELECT_DOWNLOAD:0000^Product Delivery - Download^1"
[1] "24B11B23-1669-403F-A24D-74CE72DFD42A^Z:WB:TRAINING_SUBSCRIBER:0000^Training Subscriber^1"
[2] "6A4A6543-DB9F-46F2-B3C9-62D69D28A0B6^Z:WB:LIC_MGR_HOME_REDL:0000^License Manager - Home use^1"
[3] "76B3B165-0BB4-4E3E-B61F-0C0292342CE2^Account Admin^Account Admin^1"
[4] "B3C0CE51-00EE-4A0A-B208-98653E21AE11^Z:WB:1BENTLEY_ISA_ADMIN:0000^Co-Administrator^1"
[5] "CBA225BC-680C-4627-A4F6-BED401682816^ReadOnly^ReadOnly^1"
[6] "D80CF5CF-CB6E-4424-9D8F-E29F96EBD4C9^Z:WB:MY_SELECT_CD:0000^Product Delivery - DVD^1"
[7] "E0275936-FBBB-4775-97D3-9A7D19D3E1B4^Z:WB:LICENSE_MANAGER:0000^License Manager^1"
All elements contains carat (^). so spliting each element further with ^ symbol will return four element.
But I want to join all first element then all second element and then third and so on and get the result like this -
[0]: 09A880C2-8732-408C-BA09-4AD6F0A65CE9, 24B11B23-1669-403F-A24D-74CE72DFD42A, 6A4A6543-DB9F-46F2-B3C9-62D69D28A0B6, 76B3B165-0BB4-4E3E-B61F-0C0292342CE2, B3C0CE51-00EE-4A0A-B208-98653E21AE11, CBA225BC-680C-4627-A4F6-BED401682816, D80CF5CF-CB6E-4424-9D8F-E29F96EBD4C9, E0275936-FBBB-4775-97D3-9A7D19D3E1B4
[1]: Z:WB:SELECT_DOWNLOAD:0000,Z:WB:TRAINING_SUBSCRIBER:0000, Z:WB:LIC_MGR_HOME_REDL:0000,Account Admin, Z:WB:1BENTLEY_ISA_ADMIN:0000, ReadOnly, Z:WB:MY_SELECT_CD:0000, Z:WB:LICENSE_MANAGER
[2]: Product Delivery - Download, Training Subscriber, License Manager - Home use, Account Admin, Co-Administrator, ReadOnly, Product Delivery - DVD, License Manager
[3]: 1,1,1,1,1,1,1,1
What is the quickest and simplest way of achieving this?
This is what I tried so far -
var rolearray = roleDetails.Split(',').Select(s => s.Split('^')).Select(a => new { RoleId = a[0], RoleNme = a[1], FriendlyName = a[2], IsUserInRole = a[3] });
but again this is not returning the way I need it. But I want to join all a[0]s , then all a[1] and so on
SOLUTION: After comparing solutions and ran it 10 times in a loop to see the performance I found solution suggested by Jamiec is taking less time. So selecting this solution.
Upvotes: 14
Views: 3120
Reputation: 136114
The easiest way to do this, is to simply do:
var split = roleDetails.Split(',')
.Select(x => x.Split('^').ToArray())
.ToArray();
You would then access the elements like a multi dimensional jagged array
Console.WriteLine(split[0][0]);
// result: 09A880C2-8732-408C-BA09-4AD6F0A65CE9
Live example: http://rextester.com/NEUVOR15080
And if you then want all the elements grouped
Console.WriteLine(String.Join(",",split.Select(x => x[0])));
Console.WriteLine(String.Join(",",split.Select(x => x[1])));
Console.WriteLine(String.Join(",",split.Select(x => x[2])));
Console.WriteLine(String.Join(",",split.Select(x => x[3])));
Live example: http://rextester.com/BZXLG67151
Upvotes: 10
Reputation: 22443
Fairly clean and fast...
var sets = new[]
{
new List<string>(),
new List<string>(),
new List<string>(),
new List<string>(),
};
foreach (var role in roleDetails.Split(','))
{
var details = role.Split('^');
sets[0].Add(details[0]);
sets[1].Add(details[1]);
sets[2].Add(details[2]);
sets[3].Add(details[3]);
}
var lines = sets.Select(set => string.Join(",", set)).ToArray();
... little nuts to understand and doesn't really save anything on performance ...
var ret = roleDetails.Split(',')
.Aggregate(seed: new { SBS = new[] { new StringBuilder(), new StringBuilder(),
new StringBuilder(), new StringBuilder(), },
Start = true },
func: (seed, role) =>
{
var details = role.Split('^');
if (seed.Start)
{
seed.SBS[0].Append(details[0]);
seed.SBS[1].Append(details[1]);
seed.SBS[2].Append(details[2]);
seed.SBS[3].Append(details[3]);
return new
{
seed.SBS,
Start = false,
};
}
else
{
seed.SBS[0].Append(',').Append(details[0]);
seed.SBS[1].Append(',').Append(details[1]);
seed.SBS[2].Append(',').Append(details[2]);
seed.SBS[3].Append(',').Append(details[3]);
return seed;
}
},
resultSelector: result => result.SBS.Select(sb => sb.ToString()).ToArray()
);
Upvotes: 0
Reputation: 11832
If you don't like the LINQ solutions, here's a solution without:
var result = new string[4];
var i = 0;
foreach(var line in roleDetails.Split(','))
foreach(var piece in line.Split('^'))
result[i++ % 4] += (i <= 4 ? "" : ",") + piece;
Basically, you split on commas and carets, and foreach on each, using a counter that tells us which array element to concatenate in, and whether to use a comma separator or not.
If your initial string is much bigger than in this example, consider first creating an array of StringBuilders first as these are better performing with concatenations:
var stringBuilders = new StringBuilder[4];
var result = new string[4];
var i = 0;
for (var i = 0; i < 4; i++)
stringBuilders[i] = new StringBuilder();
foreach(var line in roleDetails.Split(','))
foreach(var piece in line.Split('^'))
stringBuilders[i++ % 4].Append((i <= 4 ? "" : ",") + piece);
foreach (var stringBuilder in stringBuilders)
result[i++ % 4] = stringBuilder.ToString();
Upvotes: 1
Reputation: 8986
Pure LINQ solution:
roleDetails.Split(',')
.SelectMany(x => x.Split('^').Select((str, idx) => new {str, idx}))
.GroupBy(x => x.idx)
.Select(grp => string.Join(", ", grp.Select(x => x.str)))
Upvotes: 16
Reputation: 2121
Here you can user Aggregate and Zip extension method of Linq.
Aggregate: Performs a specified operation to each element in a collection, while carrying the result forward.
Zip: The Zip extension method acts upon two collections. It processes each element in two series together.
var roleDetails = "09A880C2-8732-408C-BA09-4AD6F0A65CE9^Z:WB:SELECT_DOWNLOAD:0000^Product Delivery - Download^1,24B11B23-1669-403F-A24D-74CE72DFD42A^Z:WB:TRAINING_SUBSCRIBER:0000^Training Subscriber^1,6A4A6543-DB9F-46F2-B3C9-62D69D28A0B6^Z:WB:LIC_MGR_HOME_REDL:0000^License Manager - Home use^1,76B3B165-0BB4-4E3E-B61F-0C0292342CE2^Account Admin^Account Admin^1,B3C0CE51-00EE-4A0A-B208-98653E21AE11^Z:WB:1BENTLEY_ISA_ADMIN:0000^Co-Administrator^1,CBA225BC-680C-4627-A4F6-BED401682816^ReadOnly^ReadOnly^1,D80CF5CF-CB6E-4424-9D8F-E29F96EBD4C9^Z:WB:MY_SELECT_CD:0000^Product Delivery - DVD^1,E0275936-FBBB-4775-97D3-9A7D19D3E1B4^Z:WB:LICENSE_MANAGER:0000^License Manager^1";
var rolearray = roleDetails.Split(',')
.Select(s => s.Split('^'))
.Aggregate((s1Array, s2Array) => s1Array.Zip(s2Array, (s1, s2) => s1 + "," + s2).ToArray());
Upvotes: 5
Reputation: 449
You can use Tuple
here
var roles = roleDetails.Split(',')
.Select(x => x.Split('^'))
.Where(x=>x.Length==4)
.Select(x=>
new Tuple<string, string, string, string>(x[0], x[1], x[2], x[3]))
.ToList();
var item1 = string.Join(",", roles.Select(x=>x.Item1).ToArray());
var item2 = string.Join(",", roles.Select(x => x.Item2).ToArray());
var item3 = string.Join(",", roles.Select(x => x.Item3).ToArray());
var item4 = string.Join(",", roles.Select(x => x.Item4).ToArray());
Upvotes: -2
Reputation: 3247
One more LINQ solution. But not as clean as @Pavel's:
string a = "", b = "", c = "", d = "";
roleDetails.Split(',').ToList().ForEach(x =>
{
a += x.Split('^')[0] + ',';
b += x.Split('^')[1] + ',';
c += x.Split('^')[2] + ',';
d += x.Split('^')[3] + ',';
});
MessageBox.Show(a.Trim(','));
MessageBox.Show(b.Trim(','));
MessageBox.Show(c.Trim(','));
MessageBox.Show(d.Trim(','));
OUTPUT:
a = 09A880C2-8732-408C-BA09-4AD6F0A65CE9,24B11B23-1669-403F-A24D-74CE72DFD42A,6A4A6543-DB9F-46F2-B3C9-62D69D28A0B6,76B3B165-0BB4-4E3E-B61F-0C0292342CE2,B3C0CE51-00EE-4A0A-B208-98653E21AE11,CBA225BC-680C-4627-A4F6-BED401682816,D80CF5CF-CB6E-4424-9D8F-E29F96EBD4C9,E0275936-FBBB-4775-97D3-9A7D19D3E1B4
b = Z:WB:SELECT_DOWNLOAD:0000,Z:WB:TRAINING_SUBSCRIBER:0000,Z:WB:LIC_MGR_HOME_REDL:0000,Account Admin,Z:WB:1BENTLEY_ISA_ADMIN:0000,ReadOnly,Z:WB:MY_SELECT_CD:0000,Z:WB:LICENSE_MANAGER:0000
c = Product Delivery - Download,Training Subscriber,License Manager - Home use,Account Admin,Co-Administrator,ReadOnly,Product Delivery - DVD,License Manager
d = 1,1,1,1,1,1,1,1
Upvotes: 0
Reputation: 34160
string roleDetails = "09A880C2-8732-408C-BA09-4AD6F0A65CE9^Z:WB:SELECT_DOWNLOAD:0000^Product Delivery - Download^1,24B11B23-1669-403F-A24D-74CE72DFD42A^Z:WB:TRAINING_SUBSCRIBER:0000^Training Subscriber^1,6A4A6543-DB9F-46F2-B3C9-62D69D28A0B6^Z:WB:LIC_MGR_HOME_REDL:0000^License Manager - Home use^1,76B3B165-0BB4-4E3E-B61F-0C0292342CE2^Account Admin^Account Admin^1,B3C0CE51-00EE-4A0A-B208-98653E21AE11^Z:WB:1BENTLEY_ISA_ADMIN:0000^Co-Administrator^1,CBA225BC-680C-4627-A4F6-BED401682816^ReadOnly^ReadOnly^1,D80CF5CF-CB6E-4424-9D8F-E29F96EBD4C9^Z:WB:MY_SELECT_CD:0000^Product Delivery - DVD^1,E0275936-FBBB-4775-97D3-9A7D19D3E1B4^Z:WB:LICENSE_MANAGER:0000^License Manager^1";
var RawItems = roleDetails.Split(',').Select(x=> x.Split('^'));
var Items1 = RawItems.Select(x=> x.ElementAt(0));
var Items2 = RawItems.Select(x=> x.ElementAt(1));
var Items3 = RawItems.Select(x=> x.ElementAt(2));
var Items4 = RawItems.Select(x=> x.ElementAt(3));
Upvotes: 1
Reputation: 13783
Your attempt tries to do everything in a single line, which is making it much harder for you to understand what's happening.
You're already using all the tools you need (Select()
and Split()
). If you make your code more readable by separating everything into separate lines of code, then it becomes much easier to find your way:
//Your data string
string myDataString = "...";
//Your data string, separated into a list of rows (each row is a string)
var myDataRows = myDataString.Split(',');
//Your data string, separated into a list of rows (each row is a STRING ARRAY)
var myDataRowsAsStringArrays = myDataRows.Select(row => row.Split('^'))
And now, all you need to do is retrieve the correct data.
var firstColumnValues = myDataRowsAsStringArrays.Select(row => row[0]);
var secondColumnValues = myDataRowsAsStringArrays.Select(row => row[1]);
var thirdColumnValues = myDataRowsAsStringArrays.Select(row => row[2]);
var fourthColumnValues = myDataRowsAsStringArrays.Select(row => row[3]);
And if you so choose, you can join the values into a single comma separated string:
var firstColumnString = String.Join(", ", firstColumnValues);
var secondColumnString = String.Join(", ", secondColumnValues);
var thirdColumnString = String.Join(", ", thirdColumnValues);
var fourthColumnString = String.Join(", ", fourthColumnValues);
Upvotes: -3