(not an actual person)
55705541;Henrik;Winther;50;7080;Børkop;hew#larsen.dk;0
60015956;Emilie;Beitzel;63;1610;København V;emb#senior.dk;1
44243159;Emilie;Kristensen;14;1125;København K;emk#jubiimail.dk;2
I want it so i can use a readline and find the index i need.
I want to use array.find to locate "Henrik;Winther" but i cant seem to skip the first 9 characters.
After finding the index, i want to use .Replace(";", " "); and display it with an write line.
Input: Henrik winther
Output:
55705541 Henrik Winther 50 7080 Børkop hew#larsen.dk
(The question has been edited heavily)
Here are the steps you can follow:
Make the input ; separated, since the strings in your database (I presume) are that way.
søgenavn = String.Join(";", søgenavn.Split());
Search for the input in the array, ignoring the case, of course
var line = databaseNavne.Where(x => x.IndexOf(søgenavn, StringComparison.OrdinalIgnoreCase) > 0).FirstOrDefault();
If line is null, no such line exists in the databaseNavne. Otherwise the line would be whatever's in the databaseNavne:
55705541;Henrik;Winther;50;7080;Børkop;hew#larsen.dk;0
You can split it with ;, chop it, cook it, boil it and do all sorts of stuffs. To get the space separated form like you showed in the question, do this:
line = String.Join(" ", line.Split(';'))
// 55705541 Henrik Winther 50 7080 Børkop hew#larsen.dk 0
The output you have shown does no have the 0 at the end though. Dunno who ate that away.
Old answer:
Considering the name is always going to be in the same position, you can use this to extract the name:
string inputStr = "55705541;Henrik;Winther;50;7080;Børkop;hew#larsen.dk;0"
string name = String.Join(" ", inputStr.Split(';').Skip(1).Take(2))
The code speaks for itself.
Split by ;. This returns an array of strings
Skip the first string, which in your example is 55705541
Then Take 2, in your example "Henrik" and "Winther". This also returns an array of strings (I said array only to keep things simple for the OP, I know it doesn't return an array)
Join the strings using a single space.
Related
I have this little project in C# where I am manipulating with files. Now my task is that I have to delete specific rows from files.
For example my file looks like this:
1-this is the first line
2-this is the second line
3-this is the third line
4-this is the fourth line
Now how can I keep only the first two rows and delete only the last two rows?
Note- this is how I read the file from my local machine:
string[] lines = File.ReadAllLines(#"C:\Users\admin\Desktop\COMMANDS.dat");
I have tried something like this but I think it's not so "efficient"
string text = File.ReadAllText(#"C:\Users\admin\Desktop\COMMANDS.dat");
text = text.Replace(lines[2], "");
text = text.Replace(lines[3], "");
File.WriteAllText(#"C:\Users\admin\Desktop\COMMANDS.dat", text);
So this actually does the job, it replaces the lines by string with an empty character but when I take a look at the file, I don't want to have 4 lines there, even though 2 of them are real strings and the other two are just empty lines... Can I manage to do this in another way?
Try replacing the newline character with an empty string:
string text = File.ReadAllText(#"C:\Users\admin\Desktop\COMMANDS.dat");
text = text.Replace(lines[2], "").Remove(Environment.NewLine, "");
text = text.Replace(lines[3], "").Remove(Environment.NewLine , "");
File.WriteAllText(#"C:\Users\admin\Desktop\COMMANDS.dat", text);
If my answer is useful, please mark it as accepted, and upvote it.
async Task Example()
{
var inputLines = await File.ReadAllLinesAsync("path/to/file.txt");
var outputLines = inputLines.Where((l, i) => i < 2);
await File.WriteAllLinesAsync("target/file.txt", outputLines);
}
What it does
Read data but not as one string but as a collection of lines
Create a new collection containing only the lines you want in your output
Write the filtered lines
Notes:
This example is not optimized for memory usage (because we read all lines and for larger files, e.g. multiple GB, this will fail). See existing answers for memory optimized version) - but: It's totally fine to do it this way if you know you have just a few k lines. (and it's faster)
Try not to "modify" strings. This will always create a copy and needs a lot of memory.
In this "Linq style" (functional) approach, we should treat data as immutable. That means: we have one variable that represents the input file and one variable that represents the result. We use declarative Linq to describe how the output should look like. "output is input where the filter index < 2 matches" instead of "if xy remove line" in an imperative style.
When I tried to split a string value of some text here with ++. I expected the result to be an empty list. Since the ++ is not found in the string some text here, the result of a Count on the List should be 0.
However, the result I get is 1 (when I Count on the List).
How am I able to determine if the string has no ++ in it ? (a Count did not work)
List<string> l = value.Split("++").ToList();
The observed behavior is by design. If delimiter is not found a collection with a single item is returned. As documentation states:
If this instance does not contain any of the characters in separator, the returned array consists of a single element that contains this instance.
If you want to check if delimiter exists you can use .Contains("++") or .IndexOf("++") != -1
By default, if no matches are found it returns the string in a array of size one.
How am I able to determine if the string has no ++ in it ?
if (value.Contains("++"))
edit: wow a bunch of answers already while i was writing this. :D
As #Gilad and others have pointed out, this is indeed the expected output. If a string does not contain the split value, the entire string is returned as the first item in the list.
If you plan on using this split value later, you can still use the .Split() method to determine if your split string is contained within the string, by simply checking if the count is equal to 1:
List<string> l = value.Split(new[] {"++"}).ToList();
if (l.Count == 1) {
//++ was not found in the string
} else {
//++ was found in the string (l.Count-1) times
}
Note of caution: It's less efficient to split a string, and allocate an array, than simply just checking with a method such as .Contains(). Use the above solution, if you may actually use the above split items later in the code.
If there is no "++" in the string, you get back the original string. If there are n "++"'s in the string, you get n+1 splits returned. You code is fine except that it needs an array passed:
var l = value.Split(new string[] {"++"}, StringSplitOptions.None).ToList();
So when l.Count() == 1 then there is no "++" in the string
if List content is:
0. line one
1. line two
2. line three
3. line four
and input string to search in list is:
string str = "three";
this way if (List.Contains(str)) it is not equal to any of exist string in list, and search result is False. Same result if I search by equals for example to get index of equal found string: int index = List.FindIndex(x => x.Equals(str));
but this way if (List.Any(str.Contains)) I got True result for search of input three because some string in list contains this input as part of string or word in string.
Question is how to properly get same result as with (List.Any(str.Contains)) but also to get this string as any other equal or with equal part exist in list to display. Find line three with input three and display line three string taken from list.
First of all List.Any(str.Contains) will not work in your case. It checks whether there is any line which is contained in the str. You need to check the opposite thing - whether there are lines which contain str:
var lines = List.Where(line => line.Contains(str));
You can use lines.Any() if you want to check if any line matched given word. Note that you can put lines to list if you want to avoid this query run twice. You also can use FindAll method of List<T> class. In this case, all matched lines will be returned as list:
var lines = List.FindAll(line => line.Contains(str));
I have a text file which contains a list of alphabetically organized variables with their variable numbers next to them formatted something like follows:
aabcdef 208
abcdefghijk 1191
bcdefga 7
cdefgab 12
defgab 100
efgabcd 999
fgabc 86
gabcdef 9
h 11
ijk 80
...
...
I would like to read each text as a string and keep it's designated id# something like read "aabcdef" and store it into an array at spot 208.
The 2 issues I'm running into are:
I've never read from file in C#, is there a way to read, say from
start of line to whitespace as a string? and then the next string as
an int until the end of line?
given the nature and size of these files I do not know the highest ID value of each file (not all numbers are used so some
files could house a number like 3000, but only actually list 200
variables) So how could I make a flexible way to store these
variables when I don't know how big the array/list/stack/etc.. would
need to be.
Basically you need a Dictionary instead of an array or list. You can read all lines with File.ReadLines method then split each of them based on space and \t (tab), like this:
var values = File.ReadLines("path")
.Select(line => line.Split(new [] { ' ', '\t' }, StringSplitOptions.RemoveEmptyEntries))
.ToDictionary(parts => int.Parse(parts[1]), parts => parts[0]);
Then values[208] will give you aabcdef. It looks like an array doesn't it :)
Also make sure you have no duplicate numbers because Dictionary keys should be unique otherwise you will get an exception.
I've been thinking about how I would improve other answers and I've found this alternative solution based on Regex which makes the search into the whole string (either coming from a file or not) safer.
Check that you can alter the whole regular expression to include other separators. Sample expression will detect spaces and tabs.
At the end of the day, I found that MatchCollection returns a safer result, since you always know that 3rd group is an integer and 2nd group is a text because regular expression does a lot of checking for you!
StringBuilder builder = new StringBuilder();
builder.AppendLine("djdodjodo\t\t3893983");
builder.AppendLine("dddfddffd\t\t233");
builder.AppendLine("djdodjodo\t\t39838");
builder.AppendLine("djdodjodo\t\t12");
builder.AppendLine("djdodjodo\t\t444");
builder.AppendLine("djdodjodo\t\t5683");
builder.Append("djdodjodo\t\t33");
// Replace this line with calling File.ReadAllText to read a file!
string text = builder.ToString();
MatchCollection matches = Regex.Matches(text, #"([^\s^\t]+)(?:[\s\t])+([0-9]+)", RegexOptions.IgnoreCase | RegexOptions.Multiline);
// Here's the magic: we convert an IEnumerable<Match> into a dictionary!
// Check that using regexps, int.Parse should never fail because
// it matched numbers only!
IDictionary<int, string> lines = matches.Cast<Match>()
.ToDictionary(match => int.Parse(match.Groups[2].Value), match => match.Groups[1].Value);
// Now you can access your lines as follows:
string value = lines[33]; // <-- By value
Update:
As we discussed in chat, this solution wasn't working in some actual use case you showed me, but it's not the approach what's not working but your particular case, because keys are "[something].[something]" (for example: address.Name).
I've changed given regular expression to ([\w\.]+)[\s\t]+([0-9]+) so it covers the case of key having a dot.
It's about improving the matching regular expression to fit your requirements! ;)
Update 2:
Since you told me that you need keys having any character, I've changed the regular expression to ([^\s^\t]+)(?:[\s\t])+([0-9]+).
Now it means that key is anything excepting spaces and tabs.
Update 3:
Also I see you're stuck in .NET 3.0 and ToDictionary was introduced in .NET 3.5. If you want to get the same approach in .NET 3.0, replace ToDictionary(...) with:
Dictionary<int, string> lines = new Dictionary<int, string>();
foreach(Match match in matches)
{
lines.Add(int.Parse(match.Groups[2].Value), match.Groups[1].Value);
}
I would like to show the differences between two blocks of text. Rather than comparing lines of text or individual characters, I would like to just compare words separated by specified characters ('\n', ' ', '\t' for example). My main reasoning for this is that the block of text that I'll be comparing generally doesn't have many line breaks in it and letter comparisons can be hard to follow.
I've come across the following O(ND) logic in C# for comparing lines and characters, but I'm sort of at a loss for how to modify it to compare words.
In addition, I would like to keep track of the separators between words and make sure they're included with the diff. So if space is replaced by a hard return, I would like that to come up as a diff.
I'm using Asp.net to display the entire block of text including the deleted original text and added new text (both will be highlighted to show that they were deleted/added). A solution that works with those technologies would be appreciated.
Any advice on how to accomplish this is appreciated?
Thanks!
Microsoft has released a diff project on CodePlex that allows you to do word, character, and line diffs. It is licensed under Microsoft Public License (Ms-PL).
https://github.com/mmanela/diffplex
Other than a few general optimizations, if you need to include the separators in the comparison you are essentially doing a character by character comparison with breaks. Though you could use the O(ND) you linked, you are going to make as many changes to it as you would basically writing your own.
The main problem with difference comparison is finding the continuation (if I delete a single word, but leave the rest the same).
If you want to use their code start with the example and do not write the deleted characters, if there are replaced characters in the same place, do not output this result. You then need to compute the longest continuous run of "changed" words, highlight this string and output.
Sorry thats not much of an answer, but for this problem the answer is basically writing and tuning the function.
Well String.Split with '\n', ' ' and '\t' as the split characters will return you an array of words in your block of text.
You could then compare each array for differences. A simple 1:1 comparison would tell you if any word had been changed. Comparing:
hello world how are you
and:
hello there how are you
would give you that world and changed to there.
What it wouldn't tell you was if words had been inserted or removed and you would still need to parse the text blocks character by character to see if any of the separator characters had been changed.
string string1 = "hello world how are you";
string string2 = "hello there how are you";
var first = string1.Split(' ');
var second = string2.Split(' ');
var primary = first.Length > second.Length ? first : second;
var secondary = primary == second ? first : second;
var difference = primary.Except(secondary).ToArray();