Text Searching and Manipulation
So the file I am importing into a ListBox
looks like this (each newline is a new item in the ListBox
):
C2 CAP-00128G 238.385 205.944 0 0402_8
C1 CAP-00128G 236.260 204.844 0 0402_8 //Same as above 1 (C2)
C18 CAP-00129G 230.960 190.619 0 0402_4
C19 CAP-00129G 248.060 195.344 0 0402_4
C63 CAP-00129G 231.535 203.844 0 0402_4
C65 CAP-00129G 232.260 195.419 0 0402_4 //Same as above 3 (C18, C19, C63)
C71 CAP-00130G 240.151 195.123 0 0402_4 //1 Occurrence
C4 CAP-00151G 247.435 202.019 90 0402_3 //1 Occurrence
L1 IND-00007G 248.110 205.719 0 0402_4 //1 Occurrence
R30 RES-00455G 273.010 184.644 0 0402_8
R9 RES-00455G 236.260 203.794 0 0402_8
R29 RES-00455G 272.960 174.694 0 0402_8 //Same as above 2 (R30, R9)
I am looking at each item in the ListBox
and grabbing the 2nd column values and seeing how many times they occur (see the numbers after the text - ie, 2, 4, 1, 1, 1, 3 when looking down the columns) and outputting it to a .txt file. Here is what it looks like (this is the first part of the .txt file the second part will be listed below).
( 1 0 1 1 0 0 0 0 "" "CAP-00128G" "" 2 0 0 0 0 0 ) // 2 = C2, C1
( 2 0 1 1 0 0 0 0 "" "CAP-00129G" "" 4 0 0 0 0 0 ) // 4 = C18, C19, C63, C65
( 3 0 1 1 0 0 0 0 "" "CAP-00130G" "" 1 0 0 0 0 0 ) // 1 = C71
( 4 0 1 1 0 0 0 0 "" "CAP-00151G" "" 1 0 0 0 0 0 ) // 1 = C4
( 5 0 1 1 0 0 0 0 "" "IND-00007G" "" 1 0 0 0 0 0 ) // 1 = L1
( 6 0 1 1 0 0 0 0 "" "RES-00455G" "" 3 0 0 0 0 0 ) // 3 = R30, R9, R29
Using this code for the above text:
List<string> partList = new List<string>();
// Builds original list first.
foreach (var item in placementOneListBox.Items) //This is getting all the lines in the ListBox and storing them in a List<string>.
{
// Creates a string of the items in the ListBox.
var newItems = item.ToString();
// Replaces any multiple spaces (tabs) with a single space.
newItems = Regex.Replace(newItems, @"\s+", " ");
// Splits each line by spaces.
var eachItem = newItems.Split(' ');
// Add each item to the List.
partList.Add(eachItem[1]);
}
Dictionary<string, int> result = new Dictionary<string, int>();
foreach (var item in partList)
{
if (result.ContainsKey(item))
result[item]++;
else
result.Add(item, 1);
}
foreach (var item in result)
{
sw.WriteLine("( " + deviceCount + " 0 1 1 0 0 0 0 \"\" \"" + item.Key + "\" \"\" " + item.Value + " 0 0 0 0 0 )");
deviceCount++;
}
Using the same ListBox
I am printing out the second half of the .txt file. The second part of the text file looks like this:
( 1 1 "DD" 1 238.385 205.944 0 1 2 0 0 "C2" "" "" "" "" 0 0 0 0 0 0 0 0 0 0 0 "" )
( 2 1 "DD" 1 236.260 204.844 0 1 2 0 0 "C1" "" "" "" "" 0 0 0 0 0 0 0 0 0 0 0 "" )
( 3 1 "DD" 1 230.960 190.619 0 1 2 0 0 "C18" "" "" "" "" 0 0 0 0 0 0 0 0 0 0 0 "" )
( 4 1 "DD" 1 248.060 195.344 0 1 2 0 0 "C19" "" "" "" "" 0 0 0 0 0 0 0 0 0 0 0 "" )
( 5 1 "DD" 1 231.535 203.844 0 1 2 0 0 "C63" "" "" "" "" 0 0 0 0 0 0 0 0 0 0 0 "" )
( 6 1 "DD" 1 232.260 195.419 0 1 2 0 0 "C65" "" "" "" "" 0 0 0 0 0 0 0 0 0 0 0 "" )
( 7 1 "DD" 1 240.151 195.123 0 1 2 0 0 "C71" "" "" "" "" 0 0 0 0 0 0 0 0 0 0 0 "" )
( 8 1 "DD" 1 247.435 202.019 90 1 2 0 0 "C4" "" "" "" "" 0 0 0 0 0 0 0 0 0 0 0 "" )
( 9 1 "DD" 1 248.110 205.719 0 1 2 0 0 "L1" "" "" "" "" 0 0 0 0 0 0 0 0 0 0 0 "" )
( 10 1 "DD" 1 273.010 184.644 0 1 2 0 0 "R30" "" "" "" "" 0 0 0 0 0 0 0 0 0 0 0 "" )
( 11 1 "DD" 1 236.260 203.794 0 1 2 0 开发者_如何学Python0 "R9" "" "" "" "" 0 0 0 0 0 0 0 0 0 0 0 "" )
( 12 1 "DD" 1 272.960 174.694 0 1 2 0 0 "R29" "" "" "" "" 0 0 0 0 0 0 0 0 0 0 0 "" )
Using the code:
foreach (var item in placementOneListBox.Items)
{
var newItems = item.ToString();
newItems = Regex.Replace(newItems, @"\s+", " ");
var eachItem = newItems.Split(' ');
sw.WriteLine("( " + lineCount + " 0 \"FD\" 1 " + eachItem[2] + " " + eachItem[3]
+ " 0 0 0 0 0 \"" + eachItem[0] + "\" \"\" \"\" \"\" \"\" 0 0 0 "
+ lineCount + " 0 0 0 0 0 0 0 \"\" )");
lineCount++;
}
sw.WriteLine(")");
sw.WriteLine(")");
sw.Close();
SO my problem is:
The second part of the file is being printed out properly except I need to replace the value that happens after "DD" in the second part of the file with the 1st (number) column in the first part of the file.. So instead of the 2nd part of the file being printed out how it is, I would like to have it printed out different depending on if it matched the values. This is what I would like to have the file look like:
( 1 1 "DD" 1 238.385 205.944 0 1 2 0 0 "C2" "" "" "" "" 0 0 0 0 0 0 0 0 0 0 0 "" )
( 2 1 "DD" 1 236.260 204.844 0 1 2 0 0 "C1" "" "" "" "" 0 0 0 0 0 0 0 0 0 0 0 "" )
( 3 1 "DD" 2 230.960 190.619 0 1 2 0 0 "C18" "" "" "" "" 0 0 0 0 0 0 0 0 0 0 0 "" )
( 4 1 "DD" 2 248.060 195.344 0 1 2 0 0 "C19" "" "" "" "" 0 0 0 0 0 0 0 0 0 0 0 "" )
( 5 1 "DD" 2 231.535 203.844 0 1 2 0 0 "C63" "" "" "" "" 0 0 0 0 0 0 0 0 0 0 0 "" )
( 6 1 "DD" 2 232.260 195.419 0 1 2 0 0 "C65" "" "" "" "" 0 0 0 0 0 0 0 0 0 0 0 "" )
( 7 1 "DD" 3 240.151 195.123 0 1 2 0 0 "C71" "" "" "" "" 0 0 0 0 0 0 0 0 0 0 0 "" )
( 8 1 "DD" 4 247.435 202.019 90 1 2 0 0 "C4" "" "" "" "" 0 0 0 0 0 0 0 0 0 0 0 "" )
( 9 1 "DD" 5 248.110 205.719 0 1 2 0 0 "L1" "" "" "" "" 0 0 0 0 0 0 0 0 0 0 0 "" )
( 10 1 "DD" 6 273.010 184.644 0 1 2 0 0 "R30" "" "" "" "" 0 0 0 0 0 0 0 0 0 0 0 "" )
( 11 1 "DD" 6 236.260 203.794 0 1 2 0 0 "R9" "" "" "" "" 0 0 0 0 0 0 0 0 0 0 0 "" )
( 12 1 "DD" 6 272.960 174.694 0 1 2 0 0 "R29" "" "" "" "" 0 0 0 0 0 0 0 0 0 0 0 "" )
- Can anyone help me figure this problem out?
EDIT:
Here is the Error I am getting.
The problem can be solved tersely and relatively easily (or not) using LINQ:
// Using the input file:
const string str = "C2 CAP-00128G 238.385 205.944 0 0402_8\n"
+ "C1 CAP-00128G 236.260 204.844 0 0402_8 #Same as above 1 (C2)\n"
+ "C18 CAP-00129G 230.960 190.619 0 0402_4 \n"
+ "C19 CAP-00129G 248.060 195.344 0 0402_4\n"
+ "C63 CAP-00129G 231.535 203.844 0 0402_4\n"
+ "C65 CAP-00129G 232.260 195.419 0 0402_4 #Same as above 3 (C18, C19, C63)\n"
+ "C71 CAP-00130G 240.151 195.123 0 0402_4 #1 Occurrence\n"
+ "C4 CAP-00151G 247.435 202.019 90 0402_3 #1 Occurrence\n"
+ "L1 IND-00007G 248.110 205.719 0 0402_4 #1 Occurrence\n"
+ "R30 RES-00455G 273.010 184.644 0 0402_8\n"
+ "R9 RES-00455G 236.260 203.794 0 0402_8\n"
+ "R29 RES-00455G 272.960 174.694 0 0402_8 #Same as above 2 (R30, R9)\n";
// And the reader (notice that by using `StringSplitOptions.RemoveEmptyEntries`
// you don't need your regular expression to normalize spacing):
var listLines = new List<string[]>();
using (var tr = new StringReader(str))
{
string l;
while ((l = tr.ReadLine()) != null)
listLines.Add(l.Split(new[] {' '},
StringSplitOptions.RemoveEmptyEntries));
}
// this is a cool trick when you need to build up a dictionary. The problem
// with using a dictionary in a case like this is that, unless you have some
// multidictionary implementation, you are going to be stuck with a lot of
// extra code that maintains the value collection (you know what I mean... the
// List<string[]> part of Dictionary<string, List<string[]>>.
var lookup = (from line in listLines group line by line[1]).ToArray();
// Part 1 -- The Select allows me to run a lambda function. In this case,
// I use a variation that provides me with a counter. Nothing really special
// here.
var part1 = lookup.Select(
(x, i) =>
string.Format(@"( {0} 0 1 1 0 0 0 0 """" ""{1}"" """" {2} 0 0 0 0 0 )",
i + 1, x.Key, x.Count()));
// And Part 2 - A little trickier. I'm using SelectMany to flatten my dictionary
// back out, but while doing so, I use an anonymous type to effectively decorate
// each line with the index of the group it belongs to. From then on it is again
// just a standard call to string.Format (which, if you aren't using it, please do.
// It's a lot more readable than string concatenations).
var part2 = lookup.SelectMany((x,i) => x.Select(y => new { Index = i, Item = y }))
.Select((x,i) => string.Format(
@"( {0} 1 ""DD"" {1} {2} {3} {4} 1 2 0 0 ""{5}"" """" """" """" 0 0 0 0 0 0 0 0 0 0 0 """" )",
i + 1, x.Index + 1, x.Item[2], x.Item[3], x.Item[4], x.Item[0] ));
// And so you can see your results in the console:
Console.WriteLine(string.Join("\n", part1));
Console.WriteLine();
Console.WriteLine(string.Join("\n", part2));
Finally, the output is:
( 1 0 1 1 0 0 0 0 "" "CAP-00128G" "" 2 0 0 0 0 0 )
( 2 0 1 1 0 0 0 0 "" "CAP-00129G" "" 4 0 0 0 0 0 )
( 3 0 1 1 0 0 0 0 "" "CAP-00130G" "" 1 0 0 0 0 0 )
( 4 0 1 1 0 0 0 0 "" "CAP-00151G" "" 1 0 0 0 0 0 )
( 5 0 1 1 0 0 0 0 "" "IND-00007G" "" 1 0 0 0 0 0 )
( 6 0 1 1 0 0 0 0 "" "RES-00455G" "" 3 0 0 0 0 0 )
( 1 1 "DD" 1 238.385 205.944 0 1 2 0 0 "C2" "" "" "" 0 0 0 0 0 0 0 0 0 0 0 "" )
( 2 1 "DD" 1 236.260 204.844 0 1 2 0 0 "C1" "" "" "" 0 0 0 0 0 0 0 0 0 0 0 "" )
( 3 1 "DD" 2 230.960 190.619 0 1 2 0 0 "C18" "" "" "" 0 0 0 0 0 0 0 0 0 0 0 "" )
( 4 1 "DD" 2 248.060 195.344 0 1 2 0 0 "C19" "" "" "" 0 0 0 0 0 0 0 0 0 0 0 "" )
( 5 1 "DD" 2 231.535 203.844 0 1 2 0 0 "C63" "" "" "" 0 0 0 0 0 0 0 0 0 0 0 "" )
( 6 1 "DD" 2 232.260 195.419 0 1 2 0 0 "C65" "" "" "" 0 0 0 0 0 0 0 0 0 0 0 "" )
( 7 1 "DD" 3 240.151 195.123 0 1 2 0 0 "C71" "" "" "" 0 0 0 0 0 0 0 0 0 0 0 "" )
( 8 1 "DD" 4 247.435 202.019 90 1 2 0 0 "C4" "" "" "" 0 0 0 0 0 0 0 0 0 0 0 "" )
( 9 1 "DD" 5 248.110 205.719 0 1 2 0 0 "L1" "" "" "" 0 0 0 0 0 0 0 0 0 0 0 "" )
( 10 1 "DD" 6 273.010 184.644 0 1 2 0 0 "R30" "" "" "" 0 0 0 0 0 0 0 0 0 0 0 "" )
( 11 1 "DD" 6 236.260 203.794 0 1 2 0 0 "R9" "" "" "" 0 0 0 0 0 0 0 0 0 0 0 "" )
( 12 1 "DD" 6 272.960 174.694 0 1 2 0 0 "R29" "" "" "" 0 0 0 0 0 0 0 0 0 0 0 "" )
Which I think is exactly what you are after.
So... hopefully there are some fun new things here to get familiar with:
- LINQ (This may change your life)
- Lambda functions
- Anonymous Types
- SelectMany (with indexer)
- String.Format
-- UPDATE --
If, as was mentioned in the quotes, you are getting the items from a listbox, you can initialize listlines
as shown here:
var listLines = from l in ListBox.Items
select l.ToString().Split(new[] {' '},
StringSplitOptions.RemoveEmptyEntries);
You no longer need the StringReader at all. Now, you might have to play with ToString() to make sure each item really is a string, as I'm not exactly sure what type the collection actually is.
It looks like a delimited file.
If you load this text file in to a DataTable
, you can query and output it as you wish by using a number of features which DataTable
offers like custom views and querying with Select
method.
You can also loop through all the rows in a table easily to perform whatever substitutions you need.
So the idea is to load the file in to a table, manipulate the table as needed, and render table's content to text for output.
精彩评论