Removing strings with duplicate letters from string array - c#

I have array of strings like
string[] A = { "abc", "cccc", "fgaeg", "def" };
I would like to obtain a list or array of strings where any letter appears only one time. I means that "cccc", "fgaeg" will be removed from input array.
I managed to do this but I feel that my way is very messy, unnecessarily complicated and not efficient.
Do you have any ideas to improve this algorythm (possibliy replacing with only one Linq query)?
My code:
var goodStrings = new List<string>();
int i = 0;
foreach (var str in A)
{
var tempArr = str.GroupBy(x => x)
.Select(x => new
{
Cnt = x.Count(),
Str = x.Key
}).ToArray();
var resultArr = tempArr.Where(g => g.Cnt > 1).Select(f => f.Str).ToArray();
if(resultArr.Length==0) goodStrings.Add(A[i]);
i++;
}

You can use Distinct method for every array item and get items with count of distinct items equals to original string length
string[] A = { "abc", "cccc", "fgaeg", "def" };
var result = A.Where(a => a.Distinct().Count() == a.Length).ToList();
You'll get list with abc and def values, as expected

Related

How to split the elements ​of an array of strings if they are equal?

Good day,
I currently have a string array like this:
string[] array = {"aa","bb","cc","dd","aa","cc","ee","ff","aa","bb"}
I would like to be able to get the positions that are the same from the same string [], example:
string[] a = {"aa","aa","aa"}
string[] b = {"bb","bb"}
string[] c = {"cc","cc"}
string[] d = {"dd"}
string[] e = {"ee"}
string[] f = {"ff"}
It should be noted that the elements of the parent matrix always change and are not always the same.
I tried with linq, but I don't get what I'm looking for.
this was my attempt with linq:
array.Where(x => array.Contains(x)).ToArray();
Thanks for help me!
Despite seeing what you ask for, the result you want is pretty limited an not useful to work with later on. You should take advantage of using the GroupBy in linq and then when you need something find it in that collection.
// your array
string[] array = {"aa","bb","cc","dd","aa","cc","ee","ff","aa","bb"};
// group by value
var groupedValues = array.GroupBy(x => x).ToList();
// get the "aa" group if exist
var aa = groupedValues.FirstOrDefault(x => x.Key == "aa");
// check if the group was found
if(aa != null)
{
// get all "aa" values in that group. This return this collection based on your inpit{ "aa", "aa", "aa" }
var allaaValues = aa.ToList();
}
Hope this is a solution you were looking for, good luck!
string[] array = { "aa", "bb", "cc", "dd", "aa", "cc", "ee", "ff", "aa", "bb" };
var splittedArray = new List<string[]>();
foreach (var strItem in array)
{
//Don't iterating duplicates
if (splittedArray.Any(si => si.Contains(strItem))) continue;
//if more then one item exists in the array getting those identic items and adding to the array list
if (array.Count(si => si.Equals(strItem)) > 0)
{
var identicItems = array
.Where(i => i.Equals(strItem))
.ToArray();
splittedArray.Add(identicItems);
}
else // Adding single item as a new array with this item
{
splittedArray.Add(new string[] { strItem });
}
}

Get all unique values out of strings

I am facing some problems while getting unique values out of strings.
Example:
string1 = "4,5"
string2 = "7,9"
string3 = "4,7,6,1"
string4 = "1"
After I need to get all unique values as an int. In this case result must be 6. But each time the number of strings can change.
Is this even possible?
Use Split and Distinct
var input = "1,3,1,2,3,43,23,54,3,4";
var result input.Split(',')
.Distinct();
Console.WriteLine(string.Join(",",result));
Output
1,3,2,43,23,54,4
Full Demo Here
Additional Resources
String.Split Method
Returns a string array that contains the substrings in this instance
that are delimited by elements of a specified string or Unicode
character array.
Enumerable.Distinct Method
Returns distinct elements from a sequence.
If "number of strings can change", let's organize them into a collection:
List<string> strings = new List<string> {
"4,5",
"7,9",
"4,7,6,1",
"1"
};
Then we can right a simple Linq:
var uniques = strings
.SelectMany(item => item.Split(',')) // split each item and flatten the result
.Select(item => int.Parse(item))
.Distinct()
.ToArray(); // let's have an array of distinct items: {4, 5, 7, 9, 6, 1}
If you want to obtain items which appears just once:
var uniques = strings
.SelectMany(item => item.Split(',')) // split each item and flatten the result
.Select(item => int.Parse(item))
.GroupBy(item => item)
.Where(item => item.Count() == 1)
.Select(group => group.Key)
.ToArray(); // let's have an array of items which appear once: {5, 9, 6}
Instead of using number of string variable you can you single instance of StringBuilder
Convert all element to array of integer.
Get Distinct/number which comes only one once by Linq
Something like this:
StringBuilder sb = new StringBuilder();
sb.Append("5,5");
sb.Append(",");
sb.Append("7,9");
sb.Append(",");
sb.Append("4,7,6,1");
sb.Append(",");
sb.Append("1");
string[] arr = sb.ToString().Split(',');
int[] test = Array.ConvertAll(arr, s => int.Parse(s));
var count = test
.GroupBy(e => e)
.Where(e => e.Count() == 1)
.Select(e => e.First()).ToList();
output:
9
4
6
POC: .netFiddler
A single line can do the job
string s = "1,3,1,2,3,43,23,54,3,4";
string[] StrArry = s.Split(',');
int[] IntArry = Array.ConvertAll(StrArry, int.Parse).Distinct().ToArray();
output
1,3,2,43,23,54,4
He can you try this out
var string1 = "4,5";
var string2 = "7,9";
var string3 = "4,7,6,1";
var string4 = "1";
var allStrings = string1 + ',' + string2 + ',' + string3 + ','+ string4;
var distinctNumbers = new List<string>(allStrings.Split(',').Distinct());
Output :
4
5
7
9
6
1
distinctNumbers = Count = 6
This is a longer one than the others, but it might be easier to understand how it works.
List<string> str = new List<string> {"1", "3", "1", "2", "3", "43", "23", "54", "3"," "4 };
List<string> foundstr = new List<string> { };
foreach (string check in str)
{
bool found = false;
//going through every single item in the list and checking if it is found in there
for (int i = 0; i < foundstr.Count; i++)
{
//if found then make found(bool) true so we don't put it in the list
if(check == foundstr[i])
{
found = true;
}
}
//checking if the string has been found and if not then add to list
if(found == false)
{
foundstr.Add(check);
}
}
foreach(string strings in foundstr)
{
Console.WriteLine(strings);
}
Console.ReadLine();

How to find the duplicates in the given string in c#

I want to find the duplicates for a given string, I tried for collections, It is working fine, but i don't know how to do it for a string.
Here is the code I tried for collections,
string name = "this is a a program program";
string[] arr = name.Split(' ');
var myList = new List<string>();
var duplicates = new List<string>();
foreach(string res in arr)
{
if (!myList.Contains(res))
{
myList.Add(res);
}
else
{
duplicates.Add(res);
}
}
foreach(string result in duplicates)
{
Console.WriteLine(result);
}
Console.ReadLine();
But I want to find the duplicates for the below string and to store it in an array. How to do that?
eg:- string aa = "elements";
In the above string i want to find the duplicate characters and store it in an array
Can anyone help me?
Linq solution:
string name = "this is a a program program";
String[] result = name.Split(' ')
.GroupBy(word => word)
.Where(chunk => chunk.Count() > 1)
.Select(chunk => chunk.Key)
.ToArray();
Console.Write(String.Join(Environment.NewLine, result));
The same princicple for duplicate characters within a string:
String source = "elements";
Char[] result = source
.GroupBy(c => c)
.Where(chunk => chunk.Count() > 1)
.Select(chunk => chunk.Key)
.ToArray();
// result = ['e']
Console.Write(String.Join(Environment.NewLine, result));
string name = "elements";
var myList = new List<char>();
var duplicates = new List<char>();
foreach (char res in name)
{
if (!myList.Contains(res))
{
myList.Add(res);
}
else if (!duplicates.Contains(res))
{
duplicates.Add(res);
}
}
foreach (char result in duplicates)
{
Console.WriteLine(result);
}
Console.ReadLine();
string is an array of chars. So, you can use your collection approach.
But, I would reccomend typed HashSet. Just load it with string and you'll get array of chars without duplicates, with preserved order.
take a look:
string s = "aaabbcdaaee";
HashSet<char> hash = new HashSet<char>(s);
HashSet<char> hashDup = new HashSet<char>();
foreach (var c in s)
if (hash.Contains(c))
hash.Remove(c);
else
hashDup.Add(c);
foreach (var x in hashDup)
Console.WriteLine(x);
Console.ReadKey();
Instead of a List<> i'd use a HashSet<> because it doesn't allow duplicates and Add returns false in that case. It's more efficient. I'd also use a Dictionary<TKey,Tvalue> instead of the list to track the count of each char:
string text = "elements";
var duplicates = new HashSet<char>();
var duplicateCounts = new Dictionary<char, int>();
foreach (char c in text)
{
int charCount = 0;
bool isDuplicate = duplicateCounts.TryGetValue(c, out charCount);
duplicateCounts[c] = ++charCount;
if (isDuplicate)
duplicates.Add(c);
}
Now you have all unique duplicate chars in the HashSet and the count of each unique char in the dictionary. In this example the set only contains e because it's three times in the string.
So you could output it in the following way:
foreach(char dup in duplicates)
Console.WriteLine("Duplicate char {0} appears {1} times in the text."
, dup
, duplicateCounts[dup]);
For what it's worth, here's a LINQ one-liner which also creates a Dictionary that only contains the duplicate chars and their count:
Dictionary<char, int> duplicateCounts = text
.GroupBy(c => c)
.Where(g => g.Count() > 1)
.ToDictionary(g => g.Key, g => g.Count());
I've shown it as second approach because you should first understand the standard way.
string name = "this is a a program program";
var arr = name.Split(' ').ToArray();
var dup = arr.Where(p => arr.Count(q => q == p) > 1).Select(p => p);
HashSet<string> hash = new HashSet<string>(dup);
string duplicate = string.Join(" ", hash);
You can do this through `LINQ
string name = "this is a a program program";
var d = name.Split(' ').GroupBy(x => x).Select(y => new { word = y.Key, Wordcount = y.Count() }).Where(z=>z.cou > 1).ToList();
Use LINQ to group values:
public static IEnumerable<T> GetDuplicates<T>(this IEnumerable<T> list)
{
return list.GroupBy(item => item).SelectMany(group => group.Skip(1));
}
public static bool HasDuplicates<T>(this IEnumerable<T> list)
{
return list.GetDuplicates().IsNotEmpty();
}
Then you use these extensions like this:
var list = new List<string> { "a", "b", "b", "c" };
var duplicatedValues = list.GetDuplicates();

Find most common element in array

I have a string array that can contains 1 or more elements with various string values. I need to find the most common string in the array.
string aPOS[] = new string[]{"11","11","18","18","11","11"};
I need to return "11" in this case.
Try something like this using LINQ.
int mode = aPOS.GroupBy(v => v)
.OrderByDescending(g => g.Count())
.First()
.Key;
If you don't like using LINQ or are using e.g. .Net 2.0 which does not have LINQ, you can use foreach loops
string[] aPOS = new string[] { "11", "11", "18", "18", "11", "11"};
var count = new Dictionary<string, int>();
foreach (string value in aPOS)
{
if (count.ContainsKey(value))
{
count[value]++;
}
else
{
count.Add(value, 1);
}
}
string mostCommonString = String.Empty;
int highestCount = 0;
foreach (KeyValuePair<string, int> pair in count)
{
if (pair.Value > highestCount)
{
mostCommonString = pair.Key;
highestCount = pair.Value;
}
}
You can do this with LINQ, the following is untested, but it should put you on the right track
var results = aPOS.GroupBy(v=>v) // group the array by value
.Select(g => new { // for each group select the value (key) and the number of items into an anonymous object
Key = g.Key,
Count = g.Count()
})
.OrderByDescending(o=>o.Count); // order the results by count
// results contains the enumerable [{Key = "11", Count = 4}, {Key="18", Count=2}]
Here's the official Group By documentation

A method to count occurrences in a list

Is there a simple way to count the number of occurrences of all elements of a list into that same list in C#?
Something like this:
using System;
using System.IO;
using System.Text.RegularExpressions;
using System.Collections.Generic;
using System.Linq;
string Occur;
List<string> Words = new List<string>();
List<string> Occurrences = new List<string>();
// ~170 elements added. . .
for (int i = 0;i<Words.Count;i++){
Words = Words.Distinct().ToList();
for (int ii = 0;ii<Words.Count;ii++){Occur = new Regex(Words[ii]).Matches(Words[]).Count;}
Occurrences.Add (Occur);
Console.Write("{0} ({1}), ", Words[i], Occurrences[i]);
}
}
How about something like this ...
var l1 = new List<int>() { 1,2,3,4,5,2,2,2,4,4,4,1 };
var g = l1.GroupBy( i => i );
foreach( var grp in g )
{
Console.WriteLine( "{0} {1}", grp.Key, grp.Count() );
}
Edit per comment: I will try and do this justice. :)
In my example, it's a Func<int, TKey> because my list is ints. So, I'm telling GroupBy how to group my items. The Func takes a int and returns the the key for my grouping. In this case, I will get an IGrouping<int,int> (a grouping of ints keyed by an int). If I changed it to (i => i.ToString() ) for example, I would be keying my grouping by a string. You can imagine a less trivial example than keying by "1", "2", "3" ... maybe I make a function that returns "one", "two", "three" to be my keys ...
private string SampleMethod( int i )
{
// magically return "One" if i == 1, "Two" if i == 2, etc.
}
So, that's a Func that would take an int and return a string, just like ...
i => // magically return "One" if i == 1, "Two" if i == 2, etc.
But, since the original question called for knowing the original list value and it's count, I just used an integer to key my integer grouping to make my example simpler.
You can do something like this to count from a list of things.
IList<String> names = new List<string>() { "ToString", "Format" };
IEnumerable<String> methodNames = typeof(String).GetMethods().Select(x => x.Name);
int count = methodNames.Where(x => names.Contains(x)).Count();
To count a single element
string occur = "Test1";
IList<String> words = new List<string>() {"Test1","Test2","Test3","Test1"};
int count = words.Where(x => x.Equals(occur)).Count();
var wordCount =
from word in words
group word by word into g
select new { g.Key, Count = g.Count() };
This is taken from one of the examples in the linqpad
public void printsOccurences(List<String> words)
{
var selectQuery =
from word in words
group word by word into g
select new {Word = g.Key, Count = g.Count()};
foreach(var word in selectQuery)
Console.WriteLine($"{word.Word}: {word.Count}");*emphasized text*
}
This is a version which avoids Linq but uses only slightly more code.
// using System.Collections.Generic;
Dictionary<int, int> oGroups = new Dictionary<int, int>();
List<int> oList = new List<int>() { 1, 2, 3, 4, 5, 2, 2, 2, 4, 4, 4, 1 };
foreach (int iCurrentValue in oList)
{
if (oGroups.ContainsKey(iCurrentValue))
oGroups[iCurrentValue]++;
else
oGroups.Add(iCurrentValue, 1);
}
foreach (KeyValuePair<int, int> oGroup in oGroups)
{
Console.WriteLine($"Value {oGroup.Key} appears {oGroup.Value} times.");
}
this code returns a dictionary that contain the world and the occurrence:
var wordsDic = Words
.GroupBy(p => p)
.ToDictionary(p => p.Key, q => q.Count());
Your outer loop is looping over all the words in the list. It's unnecessary and will cause you problems. Remove it and it should work properly.

Categories