Reputation: 2213
I have a list of accounts delimited by pipe, I need to return a list with how many times this account appears in the list. The new list must have same number of indexes as the original list.
Example:
INPUT: 111|111|222|333|333|111|333|444|555|555|111
OUTPUT: 4|4|1|3|3|4|3|1|2|2|4
So far I could manage only to retrieve a sum of accounts, but it groups them together:
string.Join("|", str.Split("|").GroupBy(Function(x) x).[Select](Function(y) y.Count()).ToList())
INPUT: 111|111|222|333|333|111|333|444|555|555|111
OUTPUT: 4|1|3|1|2
Thank you for any help
EDIT 1: Apologies, looks like I messed up with the INPUT/OUTPUT example not correlating to the requirements. I also forgot to mention another requirement - the sequence of output elements must be the same as the original (see updated INPUT/OUTPUT example).
Upvotes: 1
Views: 100
Reputation: 32288
You can split the input string using the known separator, group by the split values, the Join()
back each part with the separator using the strings on each Grouping as the iterator of the final Select()
part, where the string values of the Grouping are not actually considered, while the Group.Count()
is:
Dim input = "111|111|222|333|333|333|444|555|555"
Dim output = String.Join("|"c, acc.Split("|"c).GroupBy(Function(s) s).
Select(Function(grp) String.Join("|", grp.Select(Function(nan) grp.Count()))))
output
is 2|2|1|3|3|3|1|2|2
here.
There's an Aggregate()
variant, in case it's more interesting: you can aggregate the resulting Grouping.Count()
using a StringBuilder and Concat()
the final IEnumerable<StringBuilder>
:
Dim output = String.Concat(input.Split("|"c).GroupBy(Function(s) s).Select(Function(g)
g.Aggregate(New StringBuilder(), Function(sb, s) sb.AppendFormat("{0}|", g.Count()))))
Since it's actually a segmented - no sequential - input, a simple way is to turn the Grouping into a Dictionary and use the the sequential elements of the split input string as the Key:
Dim splitInput = input.Split("|"c)
Dim groups = splitInput.GroupBy(Function(s) s).ToDictionary(Function(g) g.Key, Function(g) g.Count)
' Aggregate using a StringBuilder
Dim output = splitInput.Aggregate(
New StringBuilder, Function(sb, s) sb.AppendFormat("{0}|", groups(s))).ToString()
' Or Join values as strings
Dim output = String.Join("|"c, splitInput.Select(Function(s) groups(s)))
Upvotes: 1
Reputation: 26926
Create a Dictionary
to map the account #s to their counts:
Dim accountCountMap = str.Split("|").GroupBy(Function(s) s) _
.Select(Function(sg) (sg.Key, sg.Count())) _
.ToDictionary(Function(kc) kc.Key, Function(kc) kc.Count)
Then use the Dictionary
to map the accounts to their accounts:
Dim ans = String.Join("|", str.Split("|").Select(Function(s) accountCountMap(s)))
Upvotes: 0