How to chop up a string with LINQ - c#

I have a string that needs to be chopped up. I'd like to do this in LINQ.
The string can have up to 32 letters.
I'd like to collect the parts in a dictionary.
The 1st part needs to have the first 4 letters.
The 2nd part needs to have the first 5 letters.
The 3rd part needs to have the first 6 letters.
etc.
The key of the dictionary is simply a counter. I don't know the length of the string, the min. length is 4.
How would I do this createively in LINQ?

I don't know if I understood correctly what you want to do, but maybe you are looking for something like this:
using System;
using System.Linq;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
var s = "This is a simple string";
var dic = Enumerable.Range(4, s.Length-3)
.Select((m, i) => new { Key = i, Value = s.Substring(0, m) })
.ToDictionary(a=>a.Key,a=>a.Value);
}
}
}

You could make it an extension:
public static Dictionary<int, String> Chop(this string str, int minLength)
{
if (str == null) throw new ArgumentException("str");
if (str.Length < minLength) throw new ArgumentException("Length of string less than minLength", "minLength");
var dict = str.TakeWhile((c, index) => index <= str.Length - minLength)
.Select((c, index) => new {
Index = index,
Value = str.Substring(0, minLength + index)
}).ToDictionary(obj => obj.Index, obj => obj.Value);
return dict;
}
Call it in this way:
Dictionary<int, String> = "Insert sample string here".Chop(4);

string word = "abcdefghijklmnopqrstuvwz";
var dict = new Dictionary<int, string>();
for(int i = 0; i < 28;i++)
{
dict[i] = new string(word.Take(i + 4).ToArray());
}

Related

Find the first non-repeated character in a string using C#

I am working to solve this problem. I have to find the first nonrepeated character in a string.
For example,
Input : “teeter”
Output: r
I am going to first use HashTables :
class Program
{
static void Main()
{
var inputString = “teeter” ;
Hashtable hashtable = new Hashtable();
int numb = 1;
for (int i=0; i< inputString.length(); i++)
{
if (!hashtable.ContainsKey(hashtable[i]))
hashtable.Add(hashtable[i], numb);
else
hashtable[hashtable[i]] = hashtable[i].Value+ 1 ;
}
}
}
Can I solve this problem using LinQ:
numb = inputString.First(1 == inputString.Where(item =>
item == hashtable[i]).Count());
My questions are :
-I have to solve this problem using LINQ and using HashTables or Dictionaries. Does my solutions ture ?
// throws an ArgumentNullException if s is null.
// throws an InvalidOperationException if there is no non repeating character.
char FirstNonRepeater(string s)
{
return s.ToLookup(c => c).First(g => g.Count() == 1).Key;
}
I don't think you need HashTable at all. Because string implements IEnumerable<char> you can use LINQ directly on your input string:
var letter = input.GroupBy(x => x).First(g => g.Count() == 1).Key;
Getting back to your HashTable solution. You 're not using it correctly. HashTable is not the same as Dictionary. It does not have key/value, it just has keys. You're looking for Dictionary here:
var inputString = "teeter";
var dict = new Dictionary<char, int>();
int numb = 1;
for (int i=0; i< inputString.length(); i++)
{
if (!dict.ContainsKey(inputString[i]))
dict.Add(inputString[i], numb);
else
dict[inputString[i]] += 1;
}
For a solution without HashTables, Dictionaries or LINQ, just remove duplicate characters from the string:
while (s.IndexOf(s[0], 1) != -1) {
s = s.Replace(s[0].ToString(), "");
}
char result = s[0];
You can check which characters are occured only once, and take first one out of these.
var inputString = “teeter” ;
var output = inputString.GroupBy(x=>x).FirstOrDefault(x=>x.Count() ==1).Key;
class Program
{
public static void Main(string[] args)
{
Console.WriteLine(FirstNonRepeated("tether"));
Console.ReadKey();
}
public static char? FirstNonRepeated(string word)
{
char[] chararray= word.ToCharArray();
Hashtable hashtable=new Hashtable();
foreach (var c in chararray)
{
if (hashtable.ContainsKey(c))
{
hashtable[c]=(int)hashtable[c]+1;
}
else
{
hashtable.Add(c,1);
}
}
foreach (var v in chararray)
{
if ((int) hashtable[v] == 1)
{
return v;
}
}
return null;
}
}

C# Reading particular values in a string

I have the following line from a string:
colors numResults="100" totalResults="6806926"
I want to extract the value 6806926 from the above string
How is it possible?
So far, I have used StringReader to read the entire string line by line.
Then what should I do?
I'm sure there's also a regex, but this string approach should work also:
string xmlLine = "[<colors numResults=\"100\" totalResults=\"6806926\">]";
string pattern = "totalResults=\"";
int startIndex = xmlLine.IndexOf(pattern);
if(startIndex >= 0)
{
startIndex += pattern.Length;
int endIndex = xmlLine.IndexOf("\"", startIndex);
if(endIndex >= 0)
{
string token = xmlLine.Substring(startIndex,endIndex - startIndex);
// if you want to calculate with it
int totalResults = int.Parse( token );
}
}
Demo
Consider the this is in Mytext of string type variable
now
Mytext.Substring(Mytext.indexof("totalResults="),7);
//the function indexof will return the point wheres the value start,
//and 7 is a length of charactors that you want to extract
I am using similar of this ........
You can read with Linq2Xml, numResults and totalResults are Attributes, and <colors numResults="100" totalResults="6806926"> is Element, so you can simply get it by nmyXmlElement.Attributes("totalResults").
This function will split the string into a list of key value pairs which you can then pull out whatever you require
static List<KeyValuePair<string, string>> getItems(string s)
{
var retVal = new List<KeyValuePair<String, string>>();
var items = s.Split(' ');
foreach (var item in items.Where(x => x.Contains("=")))
{
retVal.Add(new KeyValuePair<string, string>( item.Split('=')[0], item.Split('=')[1].Replace("\"", "") ));
}
return retVal;
}
You can use regular expressions:
string input = "colors numResults=\"100\" totalResults=\"6806926\"";
string pattern = "totalResults=\"(?<results>\\d+?)\"";
Match result = new Regex(pattern).Match(input);
Console.WriteLine(result.Groups["results"]);
Be sure to have this included:
using System.Text.RegularExpressions;

check if string contains dictionary Key -> remove key and add value

I am stuck at a function which checks a string ('14534000000875e') if it contains a letter.
If it contains a letter (a-z), remove the letter and add a string to the end.
To realize this, I have created a Dictionary<char, string> Pairs which has mapped a to 09001, b to 09002 [...] and z to 09026
This is my code so far:
public static string AlterSerial(string source)
{
Dictionary<char, string> pairs = new Dictionary<char, string>();
pairs.Add('a', "09001");
...
int index = source.IndexOf(x);
if (index != -1)
{
return source.Remove(index, 1);
}
return source;
}
How can I check if the source string contains one of the 26 keys, delete this key and add the corresponding string to the end of the source-string?
Note: the letter is not always at the end of the source.
Kind regards
Try this:
Dictionary<char, string> pairs = new Dictionary<char, string>();
pairs.Add('a', "09001");
...
foreach(KeyValuePair<string, string> entry in pairs)
{
if (source.Contains(entry.Key)) // .Key must be capitalized
{
source = source.Replace(entry.Key, "") + entry.Value;
break;
}
}
return source;
....
So this is the solution where you have only one letter within your string. You need to find the letter that is within the string, if it exists, and find its index. Then you have to insert the respective value instead of the letter, obtained from the dictionary.
String mystring = "1453400e0000875";
Dictionary<char, string> pairs = new Dictionary<char, string>();
pairs.Add('a', "09001");
pairs.Add('b', "09002");
pairs.Add('c', "09003");
pairs.Add('d', "09004");
pairs.Add('e', "09005");
//...
char letter = mystring.FirstOrDefault(a => Char.IsLetter(a));
if (letter != '\0')
{
int index = mystring.IndexOf(letter);
string substitute;
pairs.TryGetValue(mystring[index], out substitute);
mystring = mystring.Substring(0, index) + substitute + mystring.Substring(index + 1);
}
EDIT:
Using Replace method of the string, the if part can be altered like this:
char letter = mystring.FirstOrDefault(a => Char.IsLetter(a));
if (letter != '\0')
{
string substitute;
pairs.TryGetValue(letter, out substitute);
mystring = mystring.Replace(letter.ToString(), substitute);
}
EDIT2:And if I didn't understand the OP correctly so that he wants to remove the letter and add the replacement string to the end of the source string, the if statement should be like this:
if (letter != '\0')
{
string substitute;
pairs.TryGetValue(letter, out substitute);
mystring = mystring.Replace(letter.ToString(), "");
mystring += substitute;
}
and this is the generalisation when you have more letters within the string. It is the similar solution but requires to iterate over all the letters within the string.
String mystring = "1453a400e0000b875";
Dictionary<char, string> pairs = new Dictionary<char, string>();
pairs.Add('a', "09001");
pairs.Add('b', "09002");
pairs.Add('c', "09003");
pairs.Add('d', "09004");
pairs.Add('e', "09005");
//...
var lettersList = mystring.Where(a => Char.IsLetter(a));
foreach (char letter in lettersList)
{
int index = mystring.IndexOf(letter);
string substitute;
pairs.TryGetValue(mystring[index], out substitute);
mystring = mystring.Substring(0, index) + substitute + mystring.Substring(index + 1);
}
Checked and it works!
Nikola's answer is good and if you like it you should mark it as the answer. However I like this simple method (slightly borrowed a few things :p).
var Alphabet = "abcdefghijklmnopqrstuvwxyz".ToArray();
var Pairs = new Dictionary<char, string>();
for(var i = 1; i < Alphabet.Count() +1; i++)
Pairs.Add(Alphabet[i-1], "090" + (i < 10 ? "0" + i.ToString() : i.ToString()));
var Source = "14534000000875e";
var Chars = Source.Where(x => Char.IsLetter(x));
var Output = string.Empty();
foreach(var Char in Chars)
Output = Source.Replace(Char.ToString(), Pairs[Char]);
or if you want the replacement at the end and only once for repeated chars?
foreach(var Char in Chars)
Output = Source.Replace(Char.ToString(),"") + (Pairs[Char]);

Convert array of strings to Dictionary<string, int> c# then output to Visual Studio

I have an array of strings like so:
[0]Board1
[1]Messages Transmitted75877814
[2]ISR Count682900312
[3]Bus Errors0
[4]Data Errors0
[5]Receive Timeouts0
[6]TX Q Overflows0
[7]No Handler Failures0
[8]Driver Failures0
[9]Spurious ISRs0
just to clarify the numbers in the square brackets indicate the strings position in the array
I want to convert the array of strings to a dictionary with the string to the left of each number acting as the key, for example (ISR Count, 682900312)
I then want to output specific entries in the dictionary to a text box/table in visual studio (which ever is better) it would be preferable for the numbers to be left aligned.
excuse my naivety, I'm a newbie!
Pretty Simple. Tried and Tested
string[] arr = new string[] { "Board1", "ISR Count682900312", ... };
var numAlpha = new Regex("(?<Alpha>[a-zA-Z ]*)(?<Numeric>[0-9]*)");
var res = arr.ToDictionary(x => numAlpha.Match(x).Groups["Alpha"],
x => numAlpha.Match(x).Groups["Numeric"]);
string[] strings =
{
"Board1", "Messages232"
};
Dictionary<string, int> dictionary = new Dictionary<string, int>();
foreach (var s in strings)
{
int index = 0;
for (int i = 0; i < s.Length; i++)
{
if (Char.IsDigit(s[i]))
{
index = i;
break;
}
}
dictionary.Add(s.Substring(0, index), int.Parse(s.Substring(index)));
}
var stringArray = new[]
{
"[0]Board1",
"[1]Messages Transmitted75877814",
"[2]ISR Count682900312",
"[3]Bus Errors0",
"[4]Data Errors0",
"[5]Receive Timeouts0",
"[6]TX Q Overflows0",
"[7]No Handler Failures0",
"[8]Driver Failures0",
"[9]Spurious ISRs0"
};
var resultDict = stringArray.Select(s => s.Substring(3))
.ToDictionary(s =>
{
int i = s.IndexOfAny("0123456789".ToCharArray());
return s.Substring(0, i);
},
s =>
{
int i = s.IndexOfAny("0123456789".ToCharArray());
return int.Parse(s.Substring(i));
});
EDIT: If the numbers in brackets are not included in the strings, remove .Select(s => s.Substring(3)).
Here you go:
string[] strA = new string[10]
{
"Board1",
"Messages Transmitted75877814",
"ISR Count682900312",
"Bus Errors0",
"Data Errors0",
"Receive Timeouts0",
"TX Q Overflows0",
"No Handler Failures0",
"Driver Failures0",
"Spurious ISRs0"
};
Dictionary<string, int> list = new Dictionary<string, int>();
foreach (var item in strA)
{
// this Regex matches any digit one or more times so it picks
// up all of the digits on the end of the string
var match = Regex.Match(item, #"\d+");
// this code will substring out the first part and parse the second as an int
list.Add(item.Substring(0, match.Index), int.Parse(match.Value));
}

Need algorithm to make simple program (sentence permutations)

I really cant understand how to make a simple algorithm on C# to solve my problem. So, we have a sentences:
{Hello|Hi|Hi-Hi} my {mate|m8|friend|friends}.
So, my program should make a lot of sentences looks like:
Hello my mate.
Hello my m8.
Hello my friend.
Hello my friends.
Hi my mate.
...
Hi-Hi my friends.
I know, there are a lot of programs which could do this, but i'd like to make it myself. Ofcourse, it should work with this too:
{Hello|Hi|Hi-Hi} my {mate|m8|friend|friends}, {i|we} want to {tell|say} you {hello|hi|hi-hi}.
Update I just wasn't too happy about my using the regexen to parse so simple input; yet I disliked the manual index manipulation jungle found in other answers.
So I replaced the tokenizing with a Enumerator-based scanner with two alternating token-states. This is more justified by the complexity of the input, and has a 'Linqy' feel to it (although it really isn't Linq). I have kept the original Regex based parser at the end of my post for interested readers.
This just had to be solved using Eric Lippert's/IanG's CartesianProduct Linq extension method, in which the core of the program becomes:
public static void Main(string[] args)
{
const string data = #"{Hello|Hi|Hi-Hi} my {mate|m8|friend|friends}, {i|we} want to {tell|say} you {hello|hi|hi-hi}.";
var pockets = Tokenize(data.GetEnumerator());
foreach (var result in CartesianProduct(pockets))
Console.WriteLine(string.Join("", result.ToArray()));
}
Using just two regexen (chunks and legs) to do the parsing into 'pockets', it becomes a matter of writing the CartesianProduct to the console :) Here is the full working code (.NET 3.5+):
using System;
using System.Text;
using System.Text.RegularExpressions;
using System.Linq;
using System.Collections.Generic;
namespace X
{
static class Y
{
private static bool ReadTill(this IEnumerator<char> input, string stopChars, Action<StringBuilder> action)
{
var sb = new StringBuilder();
try
{
while (input.MoveNext())
if (stopChars.Contains(input.Current))
return true;
else
sb.Append(input.Current);
} finally
{
action(sb);
}
return false;
}
private static IEnumerable<IEnumerable<string>> Tokenize(IEnumerator<char> input)
{
var result = new List<IEnumerable<string>>();
while(input.ReadTill("{", sb => result.Add(new [] { sb.ToString() })) &&
input.ReadTill("}", sb => result.Add(sb.ToString().Split('|'))))
{
// Console.WriteLine("Expected cumulative results: " + result.Select(a => a.Count()).Aggregate(1, (i,j) => i*j));
}
return result;
}
public static void Main(string[] args)
{
const string data = #"{Hello|Hi|Hi-Hi} my {mate|m8|friend|friends}, {i|we} want to {tell|say} you {hello|hi|hi-hi}.";
var pockets = Tokenize(data.GetEnumerator());
foreach (var result in CartesianProduct(pockets))
Console.WriteLine(string.Join("", result.ToArray()));
}
static IEnumerable<IEnumerable<T>> CartesianProduct<T>(this IEnumerable<IEnumerable<T>> sequences)
{
IEnumerable<IEnumerable<T>> emptyProduct = new[] { Enumerable.Empty<T>() };
return sequences.Aggregate(
emptyProduct,
(accumulator, sequence) =>
from accseq in accumulator
from item in sequence
select accseq.Concat(new[] {item}));
}
}
}
Old Regex based parsing:
static readonly Regex chunks = new Regex(#"^(?<chunk>{.*?}|.*?(?={|$))+$", RegexOptions.Compiled);
static readonly Regex legs = new Regex(#"^{((?<alternative>.*?)[\|}])+(?<=})$", RegexOptions.Compiled);
private static IEnumerable<String> All(this Regex regex, string text, string group)
{
return !regex.IsMatch(text)
? new [] { text }
: regex.Match(text).Groups[group].Captures.Cast<Capture>().Select(c => c.Value);
}
public static void Main(string[] args)
{
const string data = #"{Hello|Hi|Hi-Hi} my {mate|m8|friend|friends}, {i|we} want to {tell|say} you {hello|hi|hi-hi}.";
var pockets = chunks.All(data, "chunk").Select(v => legs.All(v, "alternative"));
The rest is unchanged
Not sure what you need Linq (#user568262) or "simple" recursion (#Azad Salahli) for. Here's my take on it:
using System;
using System.Text;
class Program
{
static Random rng = new Random();
static string GetChoiceTemplatingResult(string t)
{
StringBuilder res = new StringBuilder();
for (int i = 0; i < t.Length; ++i)
if (t[i] == '{')
{
int j;
for (j = i + 1; j < t.Length; ++j)
if (t[j] == '}')
{
if (j - i < 1) continue;
var choices = t.Substring(i + 1, j - i - 1).Split('|');
res.Append(choices[rng.Next(choices.Length)]);
i = j;
break;
}
if (j == t.Length)
throw new InvalidOperationException("No matching } found.");
}
else
res.Append(t[i]);
return res.ToString();
}
static void Main(string[] args)
{
Console.WriteLine(GetChoiceTemplatingResult(
"{Hello|Hi|Hi-Hi} my {mate|m8|friend|friends}, {i|we} want to {tell|say} you {hello|hi|hi-hi}."));
}
}
As others have noted, you can solve your problem by splitting up the string into a sequence of sets, and then taking the Cartesian product of all of those sets. I wrote a bit about generating arbitrary Cartesial products here:
http://blogs.msdn.com/b/ericlippert/archive/2010/06/28/computing-a-cartesian-product-with-linq.aspx
An alternative approach, more powerful than that, is to declare a grammar for your language and then write a program that generates every string in that language. I wrote a long series of articles on how to do so. It starts here:
http://blogs.msdn.com/b/ericlippert/archive/2010/04/26/every-program-there-is-part-one.aspx
You can use a Tuple to hold index values of each collection.
For example, you would have something like:
List<string> Greetings = new List<string>()
{
"Hello",
"Hi",
"Hallo"
};
List<string> Targets = new List<string>()
{
"Mate",
"m8",
"friend",
"friends"
};
So now you have your greetings, let's create random numbers and fetch items.
static void Main(string[] args)
{
List<string> Greetings = new List<string>()
{
"Hello",
"Hi",
"Hallo"
};
List<string> Targets = new List<string>()
{
"Mate",
"m8",
"friend",
"friends"
};
var combinations = new List<Tuple<int, int>>();
Random random = new Random();
//Say you want 5 unique combinations.
while (combinations.Count < 6)
{
Tuple<int, int> tmpCombination = new Tuple<int, int>(random.Next(Greetings.Count), random.Next(Targets.Count));
if (!combinations.Contains(tmpCombination))
{
combinations.Add(tmpCombination);
}
}
foreach (var item in combinations)
{
Console.WriteLine("{0} my {1}", Greetings[item.Item1], Targets[item.Item2]);
}
Console.ReadKey();
}
This doesn't look trivial. You need to
1. do some parsing, to extract all the lists of words that you want to combine,
2. obtain all the actual combinations of these words (which is made harder by the fact that the number of lists you want to combine is not fixed)
3. rebuild the original sentence putting all the combinations in the place of the group they came from
part 1 (the parsing part) is probably the easiest: it could be done with a Regex like this
// get all the text within {} pairs
var pattern = #"\{(.*?)\}";
var query = "{Hello|Hi|Hi-Hi} my {mate|m8|friend|friends}.";
var matches = Regex.Matches(query, pattern);
// create a List of Lists
for(int i=0; i< matches.Count; i++)
{
var nl = matches[i].Groups[1].ToString().Split('|').ToList();
lists.Add(nl);
// build a "template" string like "{0} my {1}"
query = query.Replace(matches[i].Groups[1].ToString(), i.ToString());
}
for part 2 (taking a List of Lists and obtain all resulting combinations) you can refer to this answer
for part 3 (rebuilding your original sentence) you can now take the "template" string you have in query and use String.Format to substitute all the {0}, {1} .... with the combined values from part 2
// just one example,
// you will need to loop through all the combinations obtained from part 2
var OneResultingCombination = new List<string>() {"hi", "mate"};
var oneResult = string.Format(query, OneResultingCombination.ToArray());

Categories