String Operation using Linq - c#

I am trying to convert FOO BAR BAZ to "GPCSC[", "N##" using linq.
I came this close:
var res2 = new String("FOO BAR BAZ ".ToList().Select((x, i) => x = (i % 2 == 0 ? ++x : --x )).ToArray());
which outputs
GNPC#SC#[
I need to split this string into two parts so that my output will be
`"GPCSC[", "N##"`
I couldn't sort it out yet.
Any solution advice on this?
PS: I am looking for simple solution, not bunch of lines of codes
Fiddle Link : https://dotnetfiddle.net/ml8bOC

You might need to use GroupBy:
string str = "GNPC#SC#[";
var groups = str.Select((v, i) => new { Group = i % 3, Ch = v })
.GroupBy(item => item.Group == 1)
.Select(group => string.Join("", group.Select(item => item.Ch)))
.ToList();
// groups: ["GPCSC[", "N##"]

Related

C#:How to get the longest common prefix from a list of strings LINQ expression

I am trying to learn LINQ
I would like to understand how to get the longest common prefix from a list of strings
{"a","abC","abcD"}
would return "ab". Common as in at least 1 other string has it. Even though "a" is common for all 3, I would like to get "ab" because 2 elements share this prefix and "ab" is longer than "a"
It was an interesting challenge and this is my solution:
var array = new []{"a","abC","abcD"};
var longestCommonPrefix = Enumerable.Range(1, array.Max(_ => _)!.Length)
.Select(i =>
{
var grouped = array.Where(x => x.Length >= i)
.GroupBy(x => x[..i])
.Where(x => x.Count() > 1)
.OrderByDescending(x => x.Count())
.Select(x => new { LongestCommonPrefix = x.Key })
.FirstOrDefault();
return grouped?.LongestCommonPrefix ?? string.Empty;
}).Max();
var longestCommonPrefix = (words.FirstOrDefault() ?? String.Empty)
.Substring(0,
Enumerable.Range(0, words.Any() ? words.Min(x => x.Length) + 1 : 0)
.Where(x => words.Select(w => w.Substring(0, x))
.Distinct().Count() == 1).DefaultIfEmpty(0).Max()
);

Split each two-word string in a list, compare if same and count using Linq

Is it possible to split each string (containing 2 words) in a list, then compare if both words are the same and count that occurrences using Linq? For example:
Let's say I have a list containing
list[0] = "bla bla";
list[1] = "bla heh";
list[2] = "heh heh";
The output of count should be 2 in this case.
my attempt so far:
var count = lst.Count(c => c.Split(.......)....
can't get past this.
Any help would be greatly appreciated.
list.Select(c => c.Split(' ')).Count(y => y.Length >= 2 && y[0] == y[1]);
You can utilise the Select clause then the Count like so:
int count = myList.Select(s => s.Split(' '))
.Count(a => a[0] == a[1]);
or you can use Count only like this:
int count = myList.Count(s => s.Substring(0, s.IndexOf(' ')) ==
s.Substring(s.IndexOf(' ') + 1));
With the new Span<T> value type (see this article) from nuget package 'System.Memory' you can do this without any unnecessary allocations:
int count = input.Count(x =>
{
int index = x.IndexOf(' ');
if (index < 1 || index == x.Length - 1) return false;
var span = x.AsSpan();
return span.Slice(start:0, length:index) // no allocation
.SequenceEqual(
span.Slice(start: index + 1)); // no allocation
});
Same as the others, but if you would have 3 or more words it would check them against eachother and only count the arrays that have the same words everywhere.
var result = test.Select(x => x.Split(' ')).Count(x => x.All(y => x[0] == y));

create dictionary occurrences for each letter c#

We have a program that shows you how many times a letter is repeated in a text
string txt = input.text.ToLower();
txt = Regex.Replace(txt, #"\s+", "").Replace(")","").Replace("(","").Replace(".","").Replace(",","").Replace("!","").Replace("?","") ;
var letterCount = txt.Where(char.IsLetter).GroupBy(c => c).Select(v => new { Letter = v.Key, count = v.Count() });
foreach (var c in letterCount)
{
Debug.Log(string.Format("Caracterul:{0} apare {1} ori", c.Letter.ToString(), c.count));
}
And how do I give for the most repeating letter the value of 26, then for the one that repeats the less it gets 25 and for the one that only once a value in alphabetical order?
For example, the text "we are all happy"
Letter A is repeated three times and has the value of 26
For letter L 25
For P 24 and others in alphabetical order
And, finally, get their sum?
Sorry for my English!!!
You can use this LINQ approach:
string input = "we are all happy";
var allCharValues = input.ToLookup(c => c)
.Where(g => g.Key != ' ') // or you want spaces?
.OrderByDescending(g => g.Count())
.ThenBy(g => g.Key) // you mentioned alphabetical ordering if two have same count
.Select((x, index) => new { Char = x.Key, Value = 26 - index, Count = x.Count() });
foreach (var x in allCharValues)
Console.WriteLine($"Char:{x.Char} Value:{x.Value} Count:{x.Count}");
int sum = allCharValues.Select(x => x.Value).Sum();
In relation to your question about removing unwanted characters:
I think you'd be better of just keeping all characters between a and z. You could write an extension method to do this, and convert to lowercase at the same time:
public static class StringExt
{
public static string AlphabeticChars(this string self)
{
var alphabeticChars = self.Select(char.ToLower).Where(c => 'a' <= c && c <= 'z');
return new string(alphabeticChars.ToArray());
}
}
Then you can use an approach as follows. This is similar to Tim's approach, but this uses GroupBy() to count the occurrences; it also uses the new Tuple syntax from C#7 to simplify things. Note that this ALSO names the tuple properties, so they are not using the default Item1 and Item2.
string txt = "we, (are?) all! happy.";
var r = txt
.AlphabeticChars()
.GroupBy(c => c)
.Select(g => (Count: g.Count(), Char: g.Key))
.OrderByDescending(x => x.Count)
.ThenBy(x => x.Char)
.Select((v, i) => (Occurance: v, Index: 26-i));
int sum = r.Sum(c => c.Occurance.Count * c.Index);
Console.WriteLine(sum);

LINQ - Select min count

I have a list of strings which contain X in them. I want to select list(s) with the minimum count of X in them. For example:
CountMin("AXBXX", "AAX") will return AAX.
How can I write this qith LINQ in a concise way ?
public static string CountMin(IList<string> inputList)
{
if (inputList == null || !inputList.Any()) return null;
var result = inputList.Select(s => new
{
Item = s,
Count => s.Count(ch => ch == 'X')
})
.OrderBy(item => item.Count).First().Item;
}
Snippet assumes that all elements on list are different to null. If you need it, it could be easily improved.
You can also omit temporary class:
inputList.OrderBy(s => s.Count(c => c == 'X')).First();
string[] list = {"AXBXX", "AAX", "AXX"};
string result = (from word in list
select new { word, wordLen = (word.Length - (word.Replace("X", "")).Length) })
.OrderBy(x => x.wordLen).First().word;
MessageBox.Show(result);
Here's an answer that will get you all of the minimum X strings from the list.
var listOfStrings = new List<string>()
{
"AXB",
"ABXXC",
"ABX",
};
var minimumXs =
listOfStrings
.GroupBy(x => x.Count(y => y == 'X'))
.OrderBy(x => x.Key)
.Take(1)
.SelectMany(x => x);
That gives me:
AXB
ABX

LINQ orderby from specific value

Sample:
var aux = new int[] { -1,0,1,-1,2,3,4,5,6,7 }
Expected result:
{ 2,3,4,5,6,7,1,0,-1,-1 }
How?
--
Edit: Sorry for the poor question.
I want to order all from the value 2, and others who are put in the lower end (I fixed the text).
var query = aux
.OrderBy(i => i < 2 ? 2 : 1) //small numbers last
.ThenBy(i => i < 2 ? -i : i); //large numbers asc, small numbers desc
var res = aux.Where(a => a>=2 ).OrderBy (a => a)
.Concat(aux.Where (a => a <2).OrderByDescending (a => a))

Categories

Resources