How can I find a certain letter in a String in C#? - c#

How can I search a certain letter (char) in a String?
I have to code a little riddle. You basicalley have to guess the right letters of an unknown word. Only the first letter is shown.
Example: "Apple"
A____ --> that's what you actually see. Now, the player has to input a letter/char and if it is inculded in the String "Apple", the correct letter will be added.
Example: input = e
A___e
Thx.

You can use String.IndexOf.
Example:
var str = "Apple";
var c = 'p';
var i = str.IndexOf(c);
// i will be the index of the first occurrence of 'p' in str, or -1 if not found.
if (i == -1)
{
// not found
}
else
{
do
{
// do something with index i, which is != -1
i = str.IndexOf(c, i + 1);
} while (i != -1);
}

If you want to find all letter indices, you can try this LINQ solution:
var str = "Apple";
var letter = 'p';
var charIndexMap = str
.Select((ch, idx) => (ch, idx))
.GroupBy(pair => pair.ch)
.ToDictionary(entry => entry.Key,
entry => entry.Select(pair => pair.idx));
if (charIndexMap.TryGetValue(letter, out var value))
{
Console.WriteLine("[" + string.Join(", ", value) + "]");
} else
{
// not found
}
Output:
[1, 2]
Explanation:
Use Enumerable.Select to map over the characters and indices and convert them to (character, index) tuples.
Use Enumerable.GroupBy to group tuples by character.
Convert grouped results to a dictionary using Enumerable.ToDictionary, which maps each character to an IEnumerable<int> of indices.
Use Dictionary<TKey,TValue>.TryGetValue(TKey, TValue) to get the associated indices for the letter.

Related

C# RegEx Pattern to Split a String into 2 Character Substring

I am trying to figure out a regex to use to split a string into 2 character substring.
Let's say we have the following string:
string str = "Idno1";
string pattern = #"\w{2}";
Using the pattern above will get me "Id" and "no", but it will skip the "1" since it doesn't match the pattern. I would like the following results:
string str = "Idno1"; // ==> "Id" "no" "1 "
string str2 = "Id n o 2"; // ==> "Id", " n", " o", " 2"
Linq can make easy the code. Fiddle version works
The idea: I have a chunkSize = 2 as your requirement, then, Take the string at the index (2,4,6,8,...) to get the chunk of chars and Join them to string.
public static IEnumerable<string> ProperFormat(string s)
{
var chunkSize = 2;
return s.Where((x,i) => i % chunkSize == 0)
.Select((x,i) => s.Skip(i * chunkSize).Take(chunkSize))
.Select(x=> string.Join("", x));
}
With the input, I have the output
Idno1 -->
Id
no
1
Id n o 2 -->
Id
n
o
2
Linq is really better in this case. You can use this method - it will allow to split string in chunks of arbitrary size:
public static IEnumerable<string> SplitInChunks(string s, int size = 2)
{
return s.Select((c, i) => new {c, id = i / size})
.GroupBy(x => x.id, x => x.c)
.Select(g => new string(g.ToArray()));
}
But if you are bound to regex, use this code:
public static IEnumerable<string> SplitInChunksWithRegex(string s, int size = 2)
{
var regex = new Regex($".{{1,{size}}}");
return regex.Matches(s).Cast<Match>().Select(m => m.Value);
}

How to count 2 or 3 letter words in a string using asp c#

How to count 2 or 3 letter words of a string using asp csharp, eg.
string value="This is my string value";
and output should look like this
2 letter words = 2
3 letter words = 0
4 letter words = 1
Please help, Thanks in advance.
You can try something like this:
split sentence by space to get array of words
group them by length of word (and order by that length)
iterate through every group and write letter count and number of words with that letter count
code
using System.Linq;
using System.Diagnostics;
...
var words = value.Split(' ');
var groupedByLength = words.GroupBy(w => w.Length).OrderBy(x => x.Key);
foreach (var grp in groupedByLength)
{
Debug.WriteLine(string.Format("{0} letter words: {1}", grp.Key, grp.Count()));
}
First of all you need to decide what counts as a word. A naive approach is to split the string with spaces, but this will also count commas. Another approach is to use the following regex
\b\w+?\b
and collect all the matches.
Now you got all the words in a words array, we can write a LINQ query:
var query = words.Where(x => x.Length >= 2 && x.Length <= 4)
.GroupBy(x => x.Length)
.Select(x => new { CharCount = x.Key, WordCount = x.Count() });
Then you can print the query out like this:
query.ToList().ForEach(Console.WriteLine);
This prints:
{ CharCount = 4, WordCount = 1 }
{ CharCount = 2, WordCount = 2 }
You can write some code yourself to produce a more formatted output.
If i understood your question correctly
You can do it using dictionary
First split the string by space in this case
string value = "This is my string value";
string[] words = value.Split(' ');
Then loop trough array of words and set the length of each word as a key of dictionary, note that I've used string as a key, but you can modify this to your needs.
Dictionary<string, int> latteWords = new Dictionary<string,int>();
for(int i=0;i<words.Length;i++)
{
string key = words[i].Length + " letter word";
if (latteWords.ContainsKey(key))
latteWords[key] += 1;
else
latteWords.Add(key, 1);
}
And the output would be
foreach(var ind in latteWords)
{
Console.WriteLine(ind.Key + " = " + ind.Value);
}
Modify this by wish.

How to find 1 in my string but ignore -1 C#

I have a string
string test1 = "255\r\n\r\n0\r\n\r\n-1\r\n\r\n255\r\n\r\n1\r";
I want to find all the 1's in my string but not the -1's. So in my string there is only one 1. I use string.Contain("1") but this will find two 1's. So how do i do this?
You can use regular expression:
string test1 = "255\r\n\r\n0\r\n\r\n-1\r\n\r\n255\r\n\r\n1\r";
// if at least one "1", but not "-1"
if (Regex.IsMatch(test1, "(?<!-)1")) {
...
}
the pattern is exactly 1 which is not preceed by -. To find all the 1s:
var matches = Regex
.Matches(test1, "(?<!-)1")
.OfType<Match>()
.ToArray(); // if you want an array
Try this simple solution:
Note : You can convert this to extension Method Easily.
static List<int> FindIndexSpecial(string search, char find, char ignoreIfPreceededBy)
{
// Map each Character with its Index in the String
var characterIndexMapping = search.Select((x, y) => new { character = x, index = y }).ToList();
// Check the Indexes of the excluded Character
var excludeIndexes = characterIndexMapping.Where(x => x.character == ignoreIfPreceededBy).Select(x => x.index).ToList();
// Return only Indexes who match the 'find' and are not preceeded by the excluded character
return (from t in characterIndexMapping
where t.character == find && !excludeIndexes.Contains(t.index - 1)
select t.index).ToList();
}
Usage :
static void Main(string[] args)
{
string test1 = "255\r\n\r\n0\r\n\r\n-1\r\n\r\n255\r\n\r\n1\r";
var matches = FindIndexSpecial(test1, '1', '-');
foreach (int index in matches)
{
Console.WriteLine(index);
}
Console.ReadKey();
}
You could use String.Split and Enumerable.Contains or Enumerable.Where:
string[] lines = test1.Split(new[] {Environment.NewLine, "\r"}, StringSplitOptions.RemoveEmptyEntries);
bool contains1 = lines.Contains("1");
string[] allOnes = lines.Where(l => l == "1").ToArray();
String.Contains searches for sub-strings in a given string instance. Enumerable.Contains looks if there's at least one string in the string[] which equals it.

How to find maximum number of repeated string in a string in a list of string in c#

If we have a list of strings, then how we can find the list of strings that have the maximum number of repeated symbol by using LINQ.
List <string> mylist=new List <string>();
mylist.Add("%1");
mylist.Add("%136%250%3"); //s0
mylist.Add("%1%5%20%1%10%50%8%3"); // s1
mylist.Add("%4%255%20%1%14%50%8%4"); // s2
string symbol="%";
List <string> List_has_MAX_num_of_symbol= mylist.OrderByDescending(s => s.Length ==max_num_of(symbol)).ToList();
//the result should be a list of s1 + s2 since they have **8** repeated '%'
I tried
var longest = mylist.Where(s => s.Length == mylist.Max(m => m.Length)) ;
this gives me only one string not both
Here's a very simple solution, but not exactly efficient. Every element has the Count operation performed twice...
List<string> mylist = new List<string>();
mylist.Add("%1");
mylist.Add("%136%250%3"); //s0
mylist.Add("%1%5%20%1%10%50%8%3"); // s1
mylist.Add("%4%255%20%1%14%50%8%4"); // s2
char symbol = '%';
var maxRepeat = mylist.Max(item => item.Count(c => c == symbol));
var longest = mylist.Where(item => item.Count(c => c == symbol) == maxRepeat);
It will return 2 strings:
"%1%5%20%1%10%50%8%3"
"%4%255%20%1%14%50%8%4"
Here is an implementation that depends upon SortedDictionary<,> to get what you're after.
var mylist = new List<string> {"%1", "%136%250%3", "%1%5%20%1%10%50%8%3", "%4%255%20%1%14%50%8%4"};
var mappedValues = new SortedDictionary<int, IList<string>>();
mylist.ForEach(str =>
{
var count = str.Count(c => c == '%');
if (mappedValues.ContainsKey(count))
{
mappedValues[count].Add(str);
}
else
{
mappedValues[count] = new List<string> { str };
}
});
// output to validate output
foreach (var str in mappedValues.Last().Value)
{
Console.WriteLine(str);
}
Here's one using LINQ that gets the result you're after.
var result = (from str in mylist
group str by str.Count(c => c == '%')
into g
let max = (from gKey in g select g.Key).Max()
select new
{
Count = max,
List = (from str2 in g select str2)
}).LastOrDefault();
OK, here's my answer:
char symbol = '%';
var recs = mylist.Select(s => new { Str = s, Count = s.Count(c => c == symbol) });
var maxCount = recs.Max(x => x.Count);
var longest = recs.Where(x => x.Count == maxCount).Select(x => x.Str).ToList();
It is complicated because it has three lines (the char symbol = '%'; line excluded), but it counts each string only once. EZI's answer has only two lines, but it is complicated because it counts each string twice. If you really want a one-liner, here it is:
var longest = mylist.Where(x => x.Count(c => c == symbol) == mylist.Max(y => y.Count(c => c == symbol))).ToList();
but it counts each string many times. You can choose whatever complexity you want.
We can't assume that the % is always going to be the most repeated character in your list. First, we have to determine what character appears the most in an individual string for each string.
Once we have the character and it maximum occurrence, we can apply Linq to the List<string> and grab the strings that contain the character equal to its max occurrence.
using System;
using System.Collections.Generic;
using System.Linq;
public class Program
{
public static void Main()
{
List <string> mylist=new List <string>();
mylist.Add("%1");
mylist.Add("%136%250%3");
mylist.Add("%1%5%20%1%10%50%8%3");
mylist.Add("%4%255%20%1%14%50%8%4");
// Determine what character appears most in a single string in the list
char maxCharacter = ' ';
int maxCount = 0;
foreach (string item in mylist)
{
// Get the max occurrence of each character
int max = item.Max(m => item.Count(c => c == m));
if (max > maxCount)
{
maxCount = max;
// Store the character whose occurrence equals the max
maxCharacter = item.Select(c => c).Where(c => item.Count(i => i == c) == max).First();
}
}
// Print the strings containing the max character
mylist.Where(item => item.Count(c => c == maxCharacter) == maxCount)
.ToList().ForEach(Console.WriteLine);
}
}
Results:
%1%5%20%1%10%50%8%3
%4%255%20%1%14%50%8%4
Fiddle Demo
var newList = myList.maxBy(x=>x.Count(y=>y.Equals('%'))).ToList();
This should work. Please correct syntax if wrong anywhere and update here too if it works for you.

Linq Query to match string values in an xml

I have a XML document which looks like
<recipes>
<ingredient value"1">APPLE</ingredient>
<ingredient value"2">BANANA</ingredient>
<ingredient value"3">APPLE ORANGE</ingredient>
<ingredient value"4">APPLE BANANA</ingredient>
<ingredient value"5">APPLE STRAWBERRY</ingredient>
<ingredient value"6">GRAPES</ingredient>
</recipes>
Now the user inputs some string eg Apple Grapes Banana. I sort it alphabetically and try to match it with one of the values by recursively eliminating the last word using string manipulation. But I am sure there is a more efficient way to do this in Linq. I want the query to return the closest match in XML <ingredient value"4">APPLE BANANA</ingredient>.
string str = "APPLE BANANA GRAPES"; // user input arranged by ascending alphabet and capitalized
XDocument xdoc = XDocument.Load(above xml);// gets above xml
var h = xdoc.Root.Elements("ingredient").FirstOrDefault(u => u.Value == str);//recurse these steps
if (h == null)
{
str = str.Remove(str.LastIndexOf(" "));//recurse these steps
}
//check if str matches any value;
//if not remove last word from str and check again;
I would try something like this :
string str = "APPLE BANANA GRAPES";
String[] criterias = str.Split(' ');
XDocument x = XDocument.Parse(yourXmlString);
var result =
x.Root.Elements()
// count # of matches for each element
.Select(e => new {e, num = criterias.Count(c => e.Value.Contains(c))})
// order by # of matches, then alphabetically
.OrderByDescending(r => r.num).ThenBy(r => r.e.Value)
// get a combination e: XElement, num: # of matches
.FirstOrDefault();
Edit : Not sure if the matching should be a prefix of the search string. Maybe it is more something like this :
var result =
x.Root.Elements()
// get prefixes
.Where(e => str.StartsWith(e.Value))
// count matchings
.Select(e=>new {e, num=e.Value.Split(' ').Length})
// get max matchings
.OrderByDescending(r => r.num).ThenBy(r => r.e.Value)
.FirstOrDefault();
You would need multiple conditins for closest match here.
For instance
var h = xdoc.Root.Elements("ingredient").FirstOrDefault(u => str.Contains(u.value))
is a condition that would return a nearer value in the example.
I have a simple recursive to present
public string FindValueFromText(XDocument xdoc, string str)
{
while (str != "")
{
var h = xdoc.Root.Elements("ingredient").FirstOrDefault(u => u.Value == str);
if (h == null)
{
str = str.Remove(str.LastIndexOf(" "));
FindValueFromText(xdoc, str); //recursive
}
else
{
return h.Attribute("value").Value;
}
}
return "Not found value";
}
Add these lines where you want to call above method
XDocument xDoc = XDocument.Load(xmlFilePath);
string value = FindValueFromText(xDoc, "APPLE BANANA GRAPES");

Categories

Resources