Get distinct output from an array - c#

From a string array
string[] str1={"u1-u2","u1-u2","u1-u4","u4-u1"};
string[] str2 = str1.Distinct().ToArray();
Distinct elements in a arry is:"u1-u2","u1-u4","u4-u1"
But i have to get distinct output like this: "u1-u2","u1-u4".
so please help me out

You can do like this:
string[] output = str1.Select(s => new { Value = s, NormalizedValue = string.Join("-", s.Split('-').OrderBy(_ => _)) })
.GroupBy(p => p.NormalizedValue)
.Select(g => g.OrderBy(p => p.Value).First().Value)
.ToArray();

You can convert all values to their normalized form and the call Distinct() on that:
string[] output = str1.Select(string.Join("-", s.Split('-').OrderBy(x => x)))
.Distinct()
.ToArray();
(This is based on the code from Ulugbek Umirov's answer.)

Related

How to modify string list for duplicate values?

I am working on project which is asp.net mvc core. I want to replace string list of duplicate values to one with comma separated,
List<string> stringList = surveylist.Split('&').ToList();
I have string list
This generate following output:
7=55
6=33
5=MCC
4=GHI
3=ABC
1003=DEF
1003=ABC
1=JKL
And I want to change output like this
7=55
6=33
5=MCC
4=GHI
3=ABC
1003=DEF,ABC
1=JKL
Duplicate items values should be comma separated.
There are probably 20 ways to do this. One simple one would be:
List<string> newStringList = stringList
.Select(a => new { KeyValue = a.Split("=") })
.GroupBy(a => a.KeyValue[0])
.Select(a => $"{a.Select(x => x.KeyValue[0]).First()}={string.Join(",", a.Select(x => x.KeyValue[1]))}")
.ToList();
Take a look at your output. Notice that an equal sign separates each string into a key-value pair. Think about how you want to approach this problem. Is a list of strings really the structure you want to build on? You could take a different approach and use a list of KeyValuePairs or a Dictionary instead.
If you really need to do it with a List, then look at the methods LINQ's Enumerable has to offer. Namely Select and GroupBy.
You can use Select to split once more on the equal sign: .Select(s => s.Split('=')).
You can use GroupBy to group values by a key: .GroupBy(pair => pair[0]).
To join it back to a string, you can use a Select again.
An end result could look something like this:
List<string> stringList = values.Split('&')
.Select(s => {
string[] pair = s.Split('=');
return new { Key = pair[0], Value = pair[1] };
})
.GroupBy(pair => pair.Key)
.Select(g => string.Concat(
g.Key,
'=',
string.Join(
", ",
g.Select(pair => pair.Value)
)
))
.ToList();
The group contains pairs so you need to select the value of each pair and join them into a string.

C# Array of strings contains string part from another array of strings

Is there a way using LINQ, to find if string from one array of strings contains (partial) string from another array of strings? Something like this:
string[] fullStrings = { "full_xxx_part_name", "full_ccc_part_name", "full_zzz_part_name" };
string[] stringParts = { "a_part", "b_part", "c_part", "e_part" };
// compare fullStrings array with stringParts array
// full_ccc_part_name contains c_part (first match is OK, no need to find all)
// return index 1 (index 1 from fullStrings array)
This is asked rather for educational purpose.
I'm aware that Linq does not magically avoid the loop, instead does it in the background.
You can use Where + Any with string methods:
string[] matches = fullStrings
.Where(s => stringParts.Any(s.Contains))
.ToArray();
If you want to compare in a case insensitive way use IndexOf:
string[] matches = fullStrings
.Where(s => stringParts.Any(part => s.IndexOf(part, StringComparison.OrdinalIgnoreCase) >= 0))
.ToArray();
In case you want the indexes:
int[] matches = fullStrings
.Select((s, index) => (String: s, Index: index))
.Where(x => stringParts.Any(x.String.Contains))
.Select(x => x.Index)
.ToArray();
You would of course need to use some type of loop to find the index. Here is a solution using Linq.
This will return the first index if a match is found or -1 if none is found:
var index = fullStrings
.Select((s,i) => (s, i))
.Where(x => stringParts.Any(x.s.Contains))
.Select(x => x.i)
.DefaultIfEmpty(-1)
.First();

Using C# Lambda to split string and search value

I have a string with the following value:
0:12211,90:33221,23:09011
In each pair, the first value (before the : (colon)) is an employee id, the second value after is a payroll id.
So If I want to get the payroll id for employee id 23 right now I have to do:
var arrayValues=mystring.split(',');
and then for each arrayValues do the same:
var employeeData = arrayValue.split(':');
That way I will get the key and the value.
Is there a way to get the Payroll ID by a given employee id using lambda?
If the employeeId is not in the string then by default it should return the payrollid for employeeid 0 zero.
Using a Linq pipeline and anonymous objects:
"0:12211,90:33221,23:09011"
.Split(',')
.Select(x => x.Split(':'))
.Select(x => new { employeeId = x[0], payrollId = x[1] })
.Where(x=> x.employeeId == "23")
Results in this:
{
employeeId = "23",
payrollId = "09011"
}
These three lines represent your data processing and projection logic:
.Split(',')
.Select(x => x.Split(':'))
.Select(x => new { employeeId = x[0], payrollId = x[1] })
Then you can add any filtering logic with Where after this the second Select
You can try something like that
"0:12211,90:33221,23:09011"
.Split(new char[] { ',' })
.Select(c => {
var pair = c.Split(new char[] { ':' });
return new KeyValuePair<string, string>(pair[0], pair[1]);
})
.ToList();
You have to be aware of validations of data
If I were you, I'd use a dictionary. Especially if you're going to do more than one lookup.
Dictionary<int, int> employeeIDToPayrollID = "0:12211,90:33221,23:09011"
.Split(',') //Split on comma into ["0:12211", "90:33221", "23:09011"]
.Select(x => x.Split(':')) //Split each string on colon into [ ["0", "12211"]... ]
.ToDictionary(int.Parse(x => x[0]), int.Parse(x => x[1]))
and now, you just have to write employeeIDtoPayrollID[0] to get 12211 back. Notice that int.Parse will throw an exception if your IDs aren't integers. You can remove those calls if you want to have a Dictionary<string, string>.
You can use string.Split along with string.Substring.
var result =
str.Split(',')
.Where(s => s.Substring(0,s.IndexOf(":",StringComparison.Ordinal)) == "23")
.Select(s => s.Substring(s.IndexOf(":",StringComparison.Ordinal) + 1))
.FirstOrDefault();
if this logic will be used more than once then I'd put it to a method:
public string GetPayrollIdByEmployeeId(string source, string employeeId){
return source.Split(',')
.Where(s => s.Substring(0, s.IndexOf(":", StringComparison.Ordinal)) == employeeId)
.Select(s => s.Substring(s.IndexOf(":", StringComparison.Ordinal) + 1))
.FirstOrDefault();
}
Assuming you have more than three pairs in the string (how long is that string, anyway?) you can convert it to a Dictionary and use that going forward.
First, split on the comma and then on the colon and put in a Dictionary:
var empInfo = src.Split(',').Select(p => p.Split(':')).ToDictionary(pa => pa[0], pa => pa[1]);
Now, you can write a function to lookup payroll IDs from employee IDs:
string LookupPayrollID(Dictionary<string, string> empInfo, string empID) => empInfo.TryGetValue(empID, out var prID) ? prID : empInfo["0"];
And you can call it to get the answer:
var emp23prid = LookupPayrollID(empInfo, "23");
var emp32prid = LookupPayrollID(empInfo, "32");
If you just have three employees in the string, creating a Dictionary is probably overkill and a simpler answer may be appropriate, such as searching the string.

How to split a Guid List in to small part of lists

I have a Guid List type of varchar(Max). This list has lots of Guid's which cross the sql limit.SO i have break this list in to small list as shown below.
var sublists = customerList
.Select((x, i) => new { Index = i, Value = x })
.GroupBy(x => x.Index / 2000)
.Select(x => x.Select(v => v.Value.ToString()).ToList())
.ToArray();
But this list is coming in char format as shown below.
I am not getting why this is coming in char format. Am I making any mistakes?
If customerList is a big string:
var sublists = customerList
.Split(",")
.Select((x, i) => new { Index = i, Value = x })
.GroupBy(x => x.Index / 2000)
.Select(x => x.Select(v => v.Value).ToList())
.ToList();
Is the same solution as here but you must add Split Method first.
Try this:
string[] sublists = customerList.Substring(0,2000).Split(',');
sublists = sublists.Take(sublists.Length - 1).ToArray();
That should give you the results you are looking for.

Convert Colon Separated String to a Dictionary<string, string>

I have a string Number1.pdf:Alpha1.pdf; Number2.pdf:Alpha2.pdf; Number3.pdf:Alpha3.pdf; and I would like get it converted to a Dictionary.
Ditionary<Number1,Alpha1> etc.
I looked for examples online and I found most of them converting Dictionary to String.Can someone help me ?
I would go with LINQ:
var input = "Number1.pdf:Alpha1.pdf; Number2.pdf:Alpha2.pdf; Number3.pdf:Alpha3.pdf;";
var items = input.Split(new[] { ';' }, StringSplitOptions.RemoveEmptyEntries);
var result = items.Select(x => x.Split(':'))
.ToDictionary(x => x[0].Split('.').First().Trim(),
x => x[1].Split('.').First().Trim());
It will skip .pdf at the end of both keys and values (as described in question).
foreach (var i in result)
Console.WriteLine(i);
prints
[Number1, Alpha1]
[Number2, Alpha2]
[Number3, Alpha3]
string s = "Number1.pdf:Alpha1.pdf; Number2.pdf:Alpha2.pdf; Number3.pdf:Alpha3.pdf;";
var names = s.Replace(".pdf","")
.Split(";".ToCharArray(), StringSplitOptions.RemoveEmptyEntries)
.Select(x => x.Split(':'))
.ToDictionary(x => x[0].Trim(), x => x[1]);

Categories