In Elm, how can I iterate over a map? - functional-programming

I'm very new to Elm, and to FP in general, but I have a little experience with Haskell. Please forgive me if I'm not using the right terminology here.
I'm trying to do some XSLT-like things, replacing patterns in XML to convert it to HTML.
I have a map of patterns and replacements. I'm not quite sure what the best data structure is for this, but I'm trying something like:
type alias Replacement = { pattern: String, replacement: String }
type ReplacementMap = List Replacement
replacementMap : ReplacementMap
replacementMap = [ { pattern: "<head>", replacement: "<h1>" },
{ pattern: "<lg>", replacement: "<ul>" },
{ pattern: "<l>", replacement: "<li>" } ]
And then I'll do something like:
type alias Xml = String
replacePat : Xml -> Html
replacePat pat repl = replace Regex.All (regex pat) (\_ -> repl)
to replace the XML tags head, lg, and l with their HTML equivalents. What I don't know how to do yet is to iterate through my replacementMap, replacing each pattern with its replacement. Or maybe there's a better way of doing this entirely?

First, here's a working example:
import Html exposing (text)
import Regex as R
type alias Replacement = { pattern: R.Regex, replacement: String }
type alias ReplacementMap = List Replacement
type alias Xml = String
main =
let
replacements =
[ { pattern = R.regex "<head>", replacement = "<h1>" }
, { pattern = R.regex "</head>", replacement = "</h1>" }
, { pattern = R.regex "<lg>", replacement = "<ul>" }
, { pattern = R.regex "</lg>", replacement = "</ul>" }
, { pattern = R.regex "<l>", replacement = "<li>" }
, { pattern = R.regex "</l>", replacement = "</li>" }
]
example = "<head>Foo</head>"
in
text (replacePat example replacements)
replace : Replacement -> Xml -> Xml
replace replacement xml =
R.replace R.All replacement.pattern (always replacement.replacement) xml
replacePat : Xml -> ReplacementMap -> String
replacePat xml rmap =
List.foldl replace xml rmap
To approach the problem first consider your inputs and outputs:
INPUTS: a List of replacements patterns and a String of XML.
OUTPUTS: A String of HTML
When you have a collection, such as a List and you want to get a single thing (ex. a String) that's a clue that you'll need to perform some kind of reduction: You're going from many to one. Reducing a List usually means you'll be doing a fold (foldl or foldr).
foldr iterates over a list applying the provided function (in this case replace) to an item in the list and the previous result of applying the function; Except for the first iteration, during which a starting value is used (the initial XML in your case). This causes a... concatenation effect as the iteration continues. Finally, the result of the last application of the function is returned as the final value.
In otherwords, List.foldl replace xml rmap is the same as a bunch of nested function applications (calls):
replace
{ pattern = R.regex "<lg>", replacement = "<ul>" }
(replace
{ pattern = R.regex "</head>", replacement = "</h1>" }
(replace
{ pattern = R.regex "<head>", replacement = "<h1>" }
"<head>Foo</head>"))
... and so on.

Related

How to split string in C#

I have a string and I want to get this sub string. [ 10:30 to 11:30 ] .
I don't how to do it.
strong text
string a = "This is my string at -10:30 to 11:30-";
You need to use IndexOf and LastIndexOf to get the first and the last dash.
var firstDash = a.IndexOf("-");
var lastDash = a.LastIndexOf("-");
var timePeriod = a.Substring(firstDash + 1, lastDash - 1);
That should be it. Play with +1 and -1 in case I missed where the reading starts for the substring method.
You might also want to check for the result of firstDash and lastDash. If the value for any of them is -1 then the target string or character was not found.
You can get your desired string using Regex. Try below code to do that.
Regex example: Regex Test Link
CODE:
using System;
using System.Text.RegularExpressions;
public class Program
{
public static void Main()
{
string a = "This is my string at -10:30 to 11:30-";
string pat = #"[0-9]{2}:[0-9]{2}\sto\s[0-9]{2}:[0-9]{2}";
// Instantiate the regular expression object.
Regex r = new Regex(pat, RegexOptions.IgnoreCase);
// Match the regular expression pattern against a text string.
Match m = r.Match(a);
if(m.Success){
Console.WriteLine(m.Value);
}
else
{
Console.WriteLine("Nothing");
}
}
}
Let me give you the simplest code. The regex is same as the above.
String result = Regex.Match(a, "[0-9]{2}:[0-9]{2}\s*to\s*[0-9]{2}:[0-9]{2}").ToString();

How to use Unicode in Regex

I am writing one regex to find rows which matches the Unicode char in text file
!Regex.IsMatch(colCount.line, #"^"[\p{IsBasicLatin}\p{IsLatinExtended-A}\p{IsLatinExtended-B}]"+$")
below is the full code which I have written
var _fileName = #"C:\text.txt";
BadLinesLst = File
.ReadLines(_fileName, Encoding.UTF8)
.Select((line, index) =>
{
var count = line.Count(c => Delimiter == c) + 1;
if (NumberOfColumns < 0)
NumberOfColumns = count;
return new
{
line = line,
count = count,
index = index
};
})
.Where(colCount => colCount.count != NumberOfColumns || (Regex.IsMatch(colCount.line, #"[^\p{IsBasicLatin}\p{IsLatinExtended-A}\p{IsLatinExtended-B}]")))
.Select(colCount => colCount.line).ToList();
File contains below rows
264162-03,66,JITK,2007,12,874.000 ,0.000 ,0.000
6420œ50-00,67,JITK,2007,12,2292.000 ,0.000 ,0.000
4804¥75-00,67,JITK,2007,12,1810.000 ,0.000 ,0.000
If file of row contains any other char apart from BasicLatin or LatinExtended-A or LatinExtended-B then I need to get those rows.
The above Regex is not working properly, this is showing those rows as well which contains LatinExtended-A or B
You need to just put the Unicode category classes into a negated character class:
if (Regex.IsMatch(colCount.line,
#"[^\p{IsBasicLatin}\p{IsLatinExtended-A}\p{IsLatinExtended-B}]"))
{ /* Do sth here */ }
This regex will find partial matches (since the Regex.IsMatch finds pattern matches inside larger strings). The pattern will match any character other than the one in \p{IsBasicLatin}, \p{IsLatinExtended-A} and \p{IsLatinExtended-B} Unicode category sets.
You may also want to check the following code:
if (Regex.IsMatch(colCount.line,
#"^[^\p{IsBasicLatin}\p{IsLatinExtended-A}\p{IsLatinExtended-B}]*$"))
{ /* Do sth here */ }
This will return true if the whole colCount.line string does not contain any character from the 3 Unicode category classes specified in the negated character class -or- if the string is empty (if you want to disallow fetching empty strings, replace * with + at the end).

Groovy: Transforming a String into a Multimap

So I have a String which looks a little something like this:
text = "foo/bar;baz/qux"
My end goal is to split this String into a Multimap like this:
["level1" : ["foo", "baz"], "level2" : ["bar", "qux"]]
I also added Multimap-support to LinkedHashMap's metaClass:
LinkedHashMap.metaClass.multiPut << { key, value ->
delegate[key] = delegate[key] ?: []; delegate[key] += value
}
The String needs to be split at semi-colon and then again at forwardslash. Currently I'm populating my Multimap within a nested for-loop but obviously there's a Groovier way of doing this. Thus I was wondering what my options are?
I'm thinking something along the lines of:
def final myMap = text.split(';')
.collectEntries { it.split('/')
.eachWithIndex { entry, index -> ["level${index + 1}" : entry] }}
You can use withDefault on your returned Map to get rid of the ternary:
def text = "foo/bar;baz/qux;foo/bar/woo"
def result = text.split(';')*.split('/').inject([:].withDefault {[]}) { map, value ->
value.eachWithIndex { element, idx ->
map["level${idx+1}"] << element
}
map
}
assert result == [level1:['foo', 'baz', 'foo'], level2:['bar', 'qux', 'bar'], level3:['woo']]
If you don't want duplicates in your results, then you can use a Set in your withDefault (then convert back to a List afterwards):
def text = "foo/bar;baz/qux;foo/bar/woo"
def result = text.split(';')*.split('/').inject([:].withDefault {[] as Set}) { map, value ->
value.eachWithIndex { element, idx ->
map["level${idx+1}"] << element
}
map
}.collectEntries { key, value -> [key, value as List] }
assert result == [level1:['foo', 'baz'], level2:['bar', 'qux'], level3:['woo']]
My take on it, I wouldn't consider it very clever but I find it much easier to read:
def myMap = [:]
text.split(';').eachWithIndex{ entry, index ->
myMap << ["level${index + 1}": entry.split('/')]
}
If you are using Groovy 2.4.0 or above, you could use the withIndex() method which has been added to java.lang.Iterable:
def myMap = text.split(';').withIndex().collect{ entry, index ->
["level${index + 1}": entry.split('/')]
}

Split the string of a row of datatable in asp.net

I am using asp.net. I am trying to split the data which is in datatable. I have a code sample like this:
{ dt=objErrorLoggingDataAccess.GetErrorDetails(errorID);
string[] stringSeparators = new string[] { "Message" };
string error = dt.Rows[0]["Message"].ToString();
string[] test = error.Split(stringSeparators, StringSplitOptions.None);
string PageName = test[0].ToString();
PageNameLabel.Text = PageName;
stringSeparators=new string[] {HttpContext.Current.Request.Url.ToString()};
error = dt.Rows[0]["Message"].ToString();
test = error.Split(stringSeparators, StringSplitOptions.None);
string Message = test[0].ToString();
MessageLabel.Text = Message;}
in the datatable following data is there:
{....ID.......Message.......................................................................................................................
....1........http://localhost:10489/images/CategoryIcon/images Message : File does not exist. UserName: naresh#naresh.com
....2........http://localhost:10489/images/CategoryIcon/images Message : File does not exist. UserName: iswar#iswar.com}
My problem is: how can I split the Message and store in the label? I want
{http://localhost:10489/images/CategoryIcon/images}
separately and UserName separately and the message separately. How can I do that? By executing the above code I am able to split
{ http://localhost:10489/images/CategoryIcon/images
}
only. How can I split the Message column and store in pageLabel, MessageLabel, UserNamelabel?
I would use a regular expression in this case. Because only by splitting this string looks a little bit to inflexible to me.
I tested your data example against this quick and dirty RegEx:
(?<id>\d+)\.*(?<url>\w+:\/\/[\w#][\w.:#]+\/?[\w\.?=%&=\-#/$,]*)\s*Message\s*:\s*(?<message>.*)UserName:\s*(?<username>([a-zA-Z0-9_\-\.]+)#((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.)|(([a-zA-Z0-9\-]+\.)+))([a-zA-Z]{2,4}|[0-9]{1,3}))
It supports valid URLs and EMail patterns.
Regex regex = new Regex(
"(?<id>\\d+)\\.*(?<url>\\w+:\\/\\/[\\w#][\\w.:#]+\\/?[\\w\\.?"+
"=%&=\\-#/$,]*)\\s*Message\\s*:\\s*(?<message>.*)UserName:\\s"+
"*(?<username>([a-zA-Z0-9_\\-\\.]+)#((\\[[0-9]{1,3}\\.[0-9]{1"+
",3}\\.[0-9]{1,3}\\.)|(([a-zA-Z0-9\\-]+\\.)+))([a-zA-Z]{2,4}|"+
"[0-9]{1,3}))",
RegexOptions.IgnoreCase
| RegexOptions.CultureInvariant
| RegexOptions.IgnorePatternWhitespace
| RegexOptions.Compiled
);
// Capture the first Match, if any, in the InputText
Match m = regex.Match(InputText);
// Capture all Matches in the InputText
MatchCollection ms = regex.Matches(InputText);
// Test to see if there is a match in the InputText
bool IsMatch = regex.IsMatch(InputText);
// Get the names of all the named capture groups
// I included your fields as groups: id, url, message and username
string[] GroupNames = regex.GetGroupNames();
I don't know how often you need to call this code. Maybe you get in performance troubles if you have too much data. This regex is q&d - please adjust it to your needs.

Cannot convert type "char" to "string" in Foreach loop

I have a hidden field that gets populated with a javascript array of ID's. When I try to iterate the hidden field(called "hidExhibitsIDs") it gives me an error(in the title).
this is my loop:
foreach(string exhibit in hidExhibitsIDs.Value)
{
comLinkExhibitToTask.Parameters.AddWithValue("#ExhibitID", exhibit);
}
when I hover over the .value it says it is "string". But when I change the "string exhibit" to "int exhibit" it works, but gives me an internal error(not important right now).
You need to convert string to string array to using in for loop to get strings not characters as your loop suggests. Assuming comma is delimiter character in the hidden field, hidden field value will be converted to string array by split.
foreach(string exhibit in hidExhibitsIDs.Value.Split(','))
{
comLinkExhibitToTask.Parameters.AddWithValue("#ExhibitID", exhibit);
}
Value is returning a String. When you do a foreach on a String, it iterates over the individual characters in it. What does the value actually look like? You'll have to parse it correctly before you try to use the data.
Example of what your code is somewhat doing right now:
var myString = "Hey";
foreach (var c in myString)
{
Console.WriteLine(c);
}
Will output:
H
e
y
You can use Char.ToString in order to convert
Link : http://msdn.microsoft.com/en-us/library/3d315df2.aspx
Or you can use this if you want convert your tab of char
char[] tab = new char[] { 'a', 'b', 'c', 'd' };
string str = new string(tab);
Value is a string, which implements IEnumerable<char>, so when you foreach over a string, it loops over each character.
I would run the debugger and see what the actual value of the hidden field is. It can't be an array, since when the POST happens, it is converted into a string.
On the server side, The Value property of a HiddenField (or HtmlInputHidden) is just a string, whose enumerator returns char structs. You'll need to split it to iterate over your IDs.
If you set the value of the hidden field on the client side with a JavaScript array, it will be a comma-separated string on the server side, so something like this will work:
foreach(string exhibit in hidExhibitsIDs.Value.Split(','))
{
comLinkExhibitToTask.Parameters.AddWithValue("#ExhibitID", exhibit);
}
public static string reversewordsInsentence(string sentence)
{
string output = string.Empty;
string word = string.Empty;
foreach(char c in sentence)
{
if (c == ' ')
{
output = word + ' ' + output;
word = string.Empty;
}
else
{
word = word + c;
}
}
output = word + ' ' + output;
return output;
}

Resources