|
I don't think the built-in LINQ methods will help you here. But it's fairly simple to implement:
public static class Patterns
{
public static IEnumerable<string> GroupPatterns(this string pattern)
{
char prev = '\0';
char[] item = new char[pattern.Length];
int itemIndex = 0;
foreach (char c in pattern)
{
if (c != prev)
{
if (itemIndex != 0)
{
yield return new string(item, 0, itemIndex);
Array.Clear(item, 0, itemIndex);
itemIndex = 0;
}
prev = c;
}
item[itemIndex] = c;
itemIndex++;
}
if (itemIndex != 0)
{
yield return new string(item, 0, itemIndex);
}
}
}
Given the input "DDDD-AAAA-DA-AD" , that will produce:
{
"DDDD",
"-",
"AAAA",
"-",
"D",
"A",
"-",
"A",
"D"
}
As to finding the matches, it might be simpler to convert the pattern to a Regular Expression[^]:
public static class Patterns
{
...
public static Regex PatternToRegularExpression(this string pattern)
{
var parts = new List<string>();
foreach (string part in pattern.GroupPattern())
{
switch (part[0])
{
case 'D':
case 'd':
{
parts.Add("\\d{" + part.Length + "}");
break;
}
case 'A':
case 'a':
{
parts.Add("[A-Z]{" + part.Length + "}");
break;
}
default:
{
parts.Add(Regex.Escape(part));
break;
}
}
}
string regexPattern = string.Concat(parts);
return new Regex(regexPattern, RegexOptions.IgnoreCase);
}
}
For the same input, this will generate the regular expression:
\d{4}-[a-z]{4}-\d{1}[a-z]{1}-[a-z]{1}\d{1}
Regexper[^]
"These people looked deep within my soul and assigned me a number based on the order in which I joined."
- Homer
|
|
|
|
|
thaks for your input, 
|
|
|
|
|
LINQ isn't always the answer. This is the way I'd do it.
List<string> patternList = new List<string>();
foreach(char ch in pattern)
{
if (patternList.Count == 0 || !patternList.Last().Contains(ch))
{
patternList.Add(ch.ToString());
}
else
{
patternList[patternList.Count-1] += ch.ToString();
}
}
You could put this code into an extension method.
".45 ACP - because shooting twice is just silly" - JSOP, 2010
- You can never have too much ammo - unless you're swimming, or on fire. - JSOP, 2010
- When you pry the gun from my cold dead hands, be careful - the barrel will be very hot. - JSOP, 2013
|
|
|
|
|
Granted, and my solution is not a linq solution , but i started by using linq, and was surprised that this was not possible by default.
|
|
|
|
|
It's truly an issue of using the right tool for the job. While Richard's solution is indeed "LINQy", that's an awful lot of code to adhere to your requirement of being able to group characters in a string into separate strings by character.
I've seen guys get stumped for days at a time because they were trying to be "elegant". Brute force is where it's at.
EDIT ==========
Richard's solution wasn't LINQy after all.
".45 ACP - because shooting twice is just silly" - JSOP, 2010
- You can never have too much ammo - unless you're swimming, or on fire. - JSOP, 2010
- When you pry the gun from my cold dead hands, be careful - the barrel will be very hot. - JSOP, 2013
modified 9-Sep-16 8:38am.
|
|
|
|
|
hehe... been there so many times..
|
|
|
|
|
John Simmons / outlaw programmer wrote: patternList.Last()
Hey, I thought you were avoiding LINQ!
John Simmons / outlaw programmer wrote: patternList[patternList.Count-1] += ch.ToString();
String concatenation in a loop - because that never affects the performance of your code at all.
"These people looked deep within my soul and assigned me a number based on the order in which I joined."
- Homer
|
|
|
|
|
Richard Deeming wrote: Hey, I thought you were avoiding LINQ!
More accurately, I didn't say to avoid LINQ, I said LINQ wasn't appropriate the way he was trying to do it. Going out of your way to avoid a specific construct is almost as pointless as going out of your way to only use that construct. Getting the work done is much more important.
Richard Deeming wrote: String concatenation in a loop - because that never affects the performance of your code at all.
I could have done this, but I'm at work and didn't feel like retyping it. I'm pretty lazy.
patternList[patternList.Count-1] = string.Format("{0}{1}", patternList[patternList.Count-1], ch);
".45 ACP - because shooting twice is just silly" - JSOP, 2010
- You can never have too much ammo - unless you're swimming, or on fire. - JSOP, 2010
- When you pry the gun from my cold dead hands, be careful - the barrel will be very hot. - JSOP, 2013
|
|
|
|
|
But that's even worse!
"These people looked deep within my soul and assigned me a number based on the order in which I joined."
- Homer
|
|
|
|
|
Micro-optimizations are pointless when you're dealing with strings this small, with probably few (if any) repetitive calls to the method containing this code.
".45 ACP - because shooting twice is just silly" - JSOP, 2010
- You can never have too much ammo - unless you're swimming, or on fire. - JSOP, 2010
- When you pry the gun from my cold dead hands, be careful - the barrel will be very hot. - JSOP, 2013
|
|
|
|
|
 Here is my simple test utility that i used to test my code. It's not elegant but does the job.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
namespace TestSubjectMatterReco
{
class Program
{
static void Main(string[] args)
{
bool run = true;
while (run)
{
Console.WriteLine("Add string to use");
string subject = Console.ReadLine();
Console.WriteLine("Add Pattern Line to use");
string Pattern = Console.ReadLine();
var sout = Parse(subject, Pattern);
if (sout.Count() == 0)
Console.WriteLine("Unable to detect pattern");
else
{
int i = 1;
sout.ForEach(p => { Console.WriteLine($"found pattern {p} this is pattern nr {i} of {sout.Count()}"); i++; });
}
Console.WriteLine("----------------------------------");
Console.WriteLine();
Console.WriteLine("Press enter to try again , use q to qwuit");
var answer = Console.ReadLine();
if (answer=="q")
run = false;
}
}
static List<string> Parse(string subject, string pattern)
{
var subjectList = subject.Split(' ').ToList().Where(p => p.Length == pattern.Length).ToList();
string result = "";
if (subjectList.Count() > 0)
{
#region break down pattern
List<string> _patterns = new List<string>();
string patt = string.Empty;
int currindex = 0;
foreach (char c in pattern.ToCharArray())
{
currindex++;
if (patt == string.Empty)
patt = c.ToString();
else
{
if (patt.StartsWith(c.ToString()))
patt += c.ToString();
else
{
_patterns.Add(patt);
patt = c.ToString();
}
}
if(currindex == pattern.Length)
_patterns.Add(patt);
}
int indexinSubjct = 0;
#endregion
#region try to find text that fits the pattern
foreach (string pair in _patterns)
{
for (int j = subjectList.Count; j > 0; j--)
{
if (pair.StartsWith("D"))
{
if (!ParseDigit(subjectList[j-1].Substring(indexinSubjct, pair.Length)))
subjectList.Remove(subjectList[j-1]);
}
else if (pair.StartsWith("A"))
{
if (!ParseLetter(subjectList[j-1].Substring(indexinSubjct, pair.Length)))
subjectList.Remove(subjectList[j-1]);
}
else
{
string part = subjectList[j - 1].Substring(indexinSubjct, pair.Length);
if(part != pair)
subjectList.Remove(subjectList[j - 1]);
}
}
indexinSubjct += pair.Length;
}
return subjectList;
}
return new List<string>();
#endregion
}
static bool ParseLetter(string sequence)
{
return sequence.All(p => char.IsLetter(p));
}
static bool ParseDigit(string sequence)
{
return sequence.All(p => char.IsDigit(p));
}
}
}
|
|
|
|
|
var pattern = "DDDD-AA-DD";
while ( pattern.Length > 0 ) {
char ch1 = pattern[ 0 ];
string item = string.Join( "", pattern.TakeWhile( p => p == ch1 ) );
pattern = pattern.TrimStart( ch1 );
Console.WriteLine( item );
}
|
|
|
|
|
Attention Member 12106926: Please note the code shown here was written a few years ago, and has not been tested, recently. I would strongly advise you to use this code (if you find it useful) only as the basis for your own code, and, as always, to test thoroughly. Well, Sir, I am reluctant to step up to the plate when heavy-hitters like Simmons and Deeming are in the ... I'll be lucky if I don't get brained by a curvew-ball, let alone strike-out with both of them, but, I like to try and create generic solutions to tasks like cleaning-up (getting rid of unwanted whatevers at the start and end of a collection), and parsing. Here's a generic parser based on Extension Methods that will parse the OP's sample, producing an IEnumerable of List<char>:
public static class IEnumerableExtensions
{
public static IEnumerable<List<T1>> GroupByContiguous<T1>(this IEnumerable<T1> src, T1 delimiter)
{
var src1 = src.TrimStart<T1>(delimiter)
.TrimEnd<T1>(delimiter);
List<T1> srcList = src1.ToList();
T1 current;
T1 previous = srcList.First();
List<T1> element = new List<T1>();
element.Add(previous);
for (int i = 1; i < srcList.Count; i++)
{
current = srcList[i];
if (current.Equals(delimiter))
{
previous = delimiter;
continue;
}
if (! current.Equals(previous))
{
yield return element;
element = new List<T1>();
previous = current;
}
element.Add(current);
}
if (element.Count > 0) yield return element;
}
public static IEnumerable<T> TrimStart<T>(this IEnumerable<T> totrim, T trimthis)
{
return totrim.SkipWhile(itm => itm.Equals(trimthis));
}
public static IEnumerable<T> TrimEnd<T>(this IEnumerable<T> totrim, T trimthis)
{
return totrim.Reverse().SkipWhile(itm => itm.Equals(trimthis)).Reverse();
}
} Test with OP's data (with some extra delimiters thrown in for variety):
private string text = "-DDDD-AAAA-DAAD-ADDDAA---";
var parsedChars = text.GroupByContiguous<char>(delimiter: '-').ToList();
foreach (var grp in parsedChars)
{
Console.WriteLine(new string(grp.ToArray()));
}
DDDD
AAAA
D
AA
D
A
DDD
AA I've tested on basic ValueType and had no errors, but, an obvious issue when you start comparing complex objects (like instances of Classes) is: will using .Equals for the equality test suffice, or will you have to provide a custom implementation of IComparer.
«There is a spectrum, from "clearly desirable behaviour," to "possibly dodgy behavior that still makes some sense," to "clearly undesirable behavior." We try to make the latter into warnings or, better, errors. But stuff that is in the middle category you don’t want to restrict unless there is a clear way to work around it.» Eric Lippert, May 14, 2008
|
|
|
|
|
I think he wanted to know where the delimiters were as well.
".45 ACP - because shooting twice is just silly" - JSOP, 2010
- You can never have too much ammo - unless you're swimming, or on fire. - JSOP, 2010
- When you pry the gun from my cold dead hands, be careful - the barrel will be very hot. - JSOP, 2013
|
|
|
|
|
Interesting comment, John,
There are a lot of ways you could skin this cat
The result of the code I showed, because it created new groups with every break in "continuity," would not reveal exactly where the specific delimiters were.
The OP does say: "separators are not mandatory."
imho, that raises the question of why use specific delimiters; perhaps they have other purposes, perhaps the OP's intent is not clear ?
But, it's trivial to get a list of indexes of some specific char; I use an Extension method to do this, but the essence is simple:
0. create a List of Int to hold the result
1. convert the string to a List of char;
2. use 'FindIndex and 'FindLastIndex to get the first and last position of the delimiter.
3. for-loop over the range from first index to last index
4. if the char at the index position is a delimiter, add the index value to the list.
While you could Linq to do this:
List<int> ndxs = str.Select((ch, i) => (ch == delimiter) ? i : -1).Where(i => i > -1).ToList(); It's much faster to do it with a 'for loop.
«There is a spectrum, from "clearly desirable behaviour," to "possibly dodgy behavior that still makes some sense," to "clearly undesirable behavior." We try to make the latter into warnings or, better, errors. But stuff that is in the middle category you don’t want to restrict unless there is a clear way to work around it.» Eric Lippert, May 14, 2008
|
|
|
|
|
$.ajax({
type: "POST",
url: '/Account/Account_Details.aspx/Datafordownload',
data: "{'Transactionid':'" + arg + "'}",
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function (response) {
var result = JSON.parse(response.d);
var a = result["Data"][0]["CompanyName"];
$('#lbl_companyname').html(a);
$('#lbl_address').text(result["Data"][0]["Address"]);
$('#lbl_city').text(result["Data"][0]["CityName"]);
$('#lbl_state').text(result["Data"][0]["StateName"]);
$('#lbl_zipcode').text(result["Data"][0]["ZipCode"]);
$('#lbl_email').text(result["Data"][0]["EmailId"]);
$('#lbl_transc_date').text(result["Data"][0]["StartDate"]);
$('#lbl_transtype').text(result["Data"][0]["TransactionDescription"]);
$('#lbl_desc').text(result["Data"][0]["Description"]);
$('#transactiondate').text(result["Data"][0]["StartDate"]);
$('#lbl_accountbalance').text(result["Data"][0]["NetBalance"]);
$('#lbl_credit').text(result["Data"][0]["Credit"]);
},
|
|
|
|
|
Does this have something to do with C#?
|
|
|
|
|
yes after binding data in label i will use html 2canvas for downloading dynamic data which is binded in label
|
|
|
|
|
|
I think what Richard was trying to get are you sure that this is the best forum for this?
ASP.NET Discussion Boards[^] will be more suited to this type of question
Every day, thousands of innocent plants are killed by vegetarians.
Help end the violence EAT BACON
|
|
|
|
|
Hi!
I need to create a capturing console in my c# website where a PDF can be opened in the website and then you would click in the textbox eg. surname and then highlight the surname in the PDF document and then it enters the info into the textbox.
Any ideas on how I can accomplish this?
Thanks!
|
|
|
|
|
|
how can we connect a virtual RFID reader created using Rifidi to an application developed using C#.NET?
|
|
|
|
|
This[^] would certainly be a better choice to ask question about this specific product.
You always obtain more by being rather polite and armed than polite only.
|
|
|
|
|
How to work on toggle button when two text fields in which we need one field require and save data and another second filed of text control toggle button.
Pleaze help me.
|
|
|
|
|