Making a mulitdimensional jagged array - c#

I want to make a dynamic array of dynamic arrays, how can I do that?
I've tried with list of list where I use the AddRange() method.
I've also tried iterating through arrays.
Maybe it makes more sense to show what I'm trying to do. I cannot get it to work:
String[] lines = System.IO.File.ReadAllLines(fileName);
String[] linesArr;
String[][] MultiArr;
int i = 0;
foreach (string line in lines)
{
if (line.Contains("EFIX"))
{
linesArr = line.Split(delimiterChars);
for (int x = 0; x < linesArr.Length; x++)
{
MultiArr[i][x] = linesArr[x];
}
Console.WriteLine(fixationsData[i]);
i++;
}
}

LINQ makes this pretty trivial.
string[][] data = File.ReadLines(filename)
.Where(line => line.Contains("EFIX"))
.Select(line => line.Split(delimiterChars))
.ToArray();//omit this last call to allow the data to be streamed,
//greatly removing the memory footprint of the application at no real
//additional cost, assuming you have no compelling reason to eagerly
//load the whole file into memory.
foreach(var line in data)
Console.WriteLine(line);

Using a list of list of strings should work fine. Here's what I'd write.
var lines = System.IO.File.ReadAllLines(fileName);
var multiArr = new List<List<string>>();
var i = 0;
foreach (var line in lines.Where(line => line.Contains("EFIX")))
{
multiArr.Add(line.Split(delimiterChars).ToList());
Console.WriteLine(fixationsData[i]);
i++;
}

String[] lines = System.IO.File.ReadAllLines(fileName);
String[] linesArr;
List<String[]> MultiArr = new List<String[]>();
foreach (string line in lines)
{
if (line.Contains("EFIX"))
{
linesArr = line.Split(delimiterChars);
MultiArr.Add(linesArr);
Console.WriteLine(fixationsData[i]);
}
}
This is a list of string arrays. This is what you are looking for.

Related

How manipulate every string that a IList gives you?

I have a list that is given by this page http://www.codigo-postal.pt/?cp4=4710&cp3= , and as you can see if you visited the link there's a line that always end with the word "Braga", so with no further ado, what I want is to manipulate every string that the list gives me, into last word after the comma?
The List is given by this code:
IList<string> Distritos = new List<string>();
foreach (var Distritoelemen in Gdriver.FindElements(By.ClassName("local")))
{
//Distritos.Add(Distritoelement.Text);
table.Rows.Add(Distritoelement.Text);
}
In order to get the word after the last comma, run this code...
IList<string> Distritos = new List<string>();
foreach (var Distritoelemen in Gdriver.FindElements(By.ClassName("local")))
{
//Distritos.Add(Distritoelement.Text);
table.Rows.Add(Distritoelement.Text.Substring(Distritoelement.Text.LastIndexOf(',') + 1));
You might want to consider putting the Text into a local variable. If you don't want the extra space before the word, you can use .Trim() on the result of Substring as in ...LastIndexOf(',') + 1).Trim());
And if you have more then one list you should do
IList<string> Freguseia = new List<string>();
foreach (var freguesiaelement in Fdriver.FindElements(By.ClassName("local")))
{
Freguseia.Add(freguesiaelement.Text);
}
IList<string> GPS = new List<string>();
foreach (var gpselement in Fdriver.FindElements(By.ClassName("gps")))
{
GPS.Add(gpselement.Text);
}
for (int i = 0; i < Freguseia.Count; i++)
{
table.Rows.Add( Freguseia.ElementAt(i), GPS.ElementAt(i));
}

Read and process 100 text files in c# in parallel

I have project that reads 100 text file with 5000 words in it.
I insert the words into a list. I have a second list that contains english stop words. I compare the two lists and delete the stop words from first list.
It takes 1 hour to run the application. I want to be parallelize it. How can I do that?
Heres my code:
private void button1_Click(object sender, EventArgs e)
{
List<string> listt1 = new List<string>();
string line;
for (int ii = 1; ii <= 49; ii++)
{
string d = ii.ToString();
using (StreamReader reader = new StreamReader(#"D" + d.ToString() + ".txt"))
while ((line = reader.ReadLine()) != null)
{
string[] words = line.Split(' ');
for (int i = 0; i < words.Length; i++)
{
listt1.Add(words[i].ToString());
}
}
listt1 = listt1.ConvertAll(d1 => d1.ToLower());
StreamReader reader2 = new StreamReader("stopword.txt");
List<string> listt2 = new List<string>();
string line2;
while ((line2 = reader2.ReadLine()) != null)
{
string[] words2 = line2.Split('\n');
for (int i = 0; i < words2.Length; i++)
{
listt2.Add(words2[i]);
}
listt2 = listt2.ConvertAll(d1 => d1.ToLower());
}
for (int i = 0; i < listt1.Count(); i++)
{
for (int j = 0; j < listt2.Count(); j++)
{
listt1.RemoveAll(d1 => d1.Equals(listt2[j]));
}
}
listt1=listt1.Distinct().ToList();
textBox1.Text = listt1.Count().ToString();
}
}
}
}
I fixed many things up with your code. I don't think you need multi-threading:
private void RemoveStopWords()
{
HashSet<string> stopWords = new HashSet<string>();
using (var stopWordReader = new StreamReader("stopword.txt"))
{
string line2;
while ((line2 = stopWordReader.ReadLine()) != null)
{
string[] words2 = line2.Split('\n');
for (int i = 0; i < words2.Length; i++)
{
stopWords.Add(words2[i].ToLower());
}
}
}
var fileWords = new HashSet<string>();
for (int fileNumber = 1; fileNumber <= 49; fileNumber++)
{
using (var reader = new StreamReader("D" + fileNumber.ToString() + ".txt"))
{
string line;
while ((line = reader.ReadLine()) != null)
{
foreach(var word in line.Split(' '))
{
fileWords.Add(word.ToLower());
}
}
}
}
fileWords.ExceptWith(stopWords);
textBox1.Text = fileWords.Count().ToString();
}
You are reading through the list of stopwords many times as well as continually adding to the list and re-attempting to remove the same stopwords over and again due to the way your code is structured. Your needs are also better matched to a HashSet than to a List, as it has set based operations and uniqueness already handled.
If you still wanted to make this parallel, you could do it by reading the stopword list once and passing it to an async method that will read the input file, remove the stopwords and return the resulting list, then you would need to merge the resulting lists after the asynchronous calls came back, but you had better test before deciding you need that, because that is quite a bit more work and complexity than this code already has.
If I understand you correctly, you want to:
Read all words from a file into a List
Remove all "stop words" from the List
Repeat for 99 more files, saving only the unique words
If this is correct, the code is pretty simple:
// The list of words to delete ("stop words")
var stopWords = new List<string> { "remove", "these", "words" };
// The list of files to check - you can get this list in other ways
var filesToCheck = new List<string>
{
#"f:\public\temp\temp1.txt",
#"f:\public\temp\temp2.txt",
#"f:\public\temp\temp3.txt"
};
// This list will contain all the unique words from all
// the files, except the ones in the "stopWords" list
var uniqueFilteredWords = new List<string>();
// Loop through all our files
foreach (var fileToCheck in filesToCheck)
{
// Read all the file text into a varaible
var fileText = File.ReadAllText(fileToCheck);
// Split the text into distinct words (splitting on null
// splits on all whitespace) and ignore empty lines
var fileWords = fileText.Split(null)
.Where(line => !string.IsNullOrWhiteSpace(line))
.Distinct();
// Add all the words from the file, except the ones in
// your "stop list" and those that are already in the list
uniqueFilteredWords.AddRange(fileWords.Except(stopWords)
.Where(word => !uniqueFilteredWords.Contains(word)));
}
This can be condensed into a single line with no explicit loop:
// This list will contain all the unique words from all
// the files, except the ones in the "stopWords" list
var uniqueFilteredWords = filesToCheck.SelectMany(fileToCheck =>
File.ReadAllText(fileToCheck)
.Split(null)
.Where(word => !string.IsNullOrWhiteSpace(word) &&
!stopWords.Any(stopWord => stopWord.Equals(word,
StringComparison.OrdinalIgnoreCase)))
.Distinct());
This code processed over 100 files with more than 12000 words each in less than a second (WAY less than a second... 0.0001782 seconds)
One issue I see here that can help improve performance is listt1.ConvertAll() will run in O(n) on the list. You are already looping to add the items to the list, why not convert them to lower case there. Also why not store the words in a hash set, so you can do look up and insertion in O(1). You could store the list of stop words in a hash set and when you are reading your text input see if the word is a stop word and if its not add it to the hash set to output the user.

How do I return lengths of string in an array?

I have an array of strings and want to output those that are of a certain length from the array.
string[]myArray = {"stringone", "stringtwo", "stringthree"};
I have tried doing
foreach(thing in myArray){
if(thing.length<10){
do stuff
}
#output
But doesnt work. Where am i going wrong?
I'm using C# in asp.net.
Many thanks.
you need to specify that thing is a string or var.
Also, you need to capitalize Length.
public void McTester()
{
string[] myArray = { "stringone", "stringtwo", "stringthree" };
foreach (string thing in myArray)
{
if (thing.Length < 10)
{
//do stuff
}
}
}
string[] myArray = { "stringone", "stringtwo", "stringthree" };
var lessThan10Length = myArray.Where(x=> x.Length < 10).ToList();
Assuming your problem was length instead of Length, you can filter out only the values you need using a Where clause:
string[] myArray = { "stringone", "stringtwo", "stringthree" };
foreach (string thing in myArray.Where(thing => thing.Length < 10))
{
// Here you'll only iterate values
// whos length is less than 10
}

How do I make the foreach instruction iterate in 2 places?

how do I make the foreach instruction iterate both in the "files" variable and in the "names" array?
var files = Directory.GetFiles(#".\GalleryImages");
string[] names = new string[8] { "Matt", "Joanne", "Robert","Andrei","Mihai","Radu","Ionica","Vasile"};
I've tried 2 options.. the first one gives me lots of errors and the second one displays 8 images of each kind
foreach(var file in files,var i in names)
{
//Do stuff
}
and
foreach(var file in files)
{
foreach (var i in names)
{
//Do stuff
}
}
You can try using the Zip Extension method of LINQ:
int[] numbers = { 1, 2, 3, 4 };
string[] words = { "one", "two", "three" };
var numbersAndWords = numbers.Zip(words, (first, second) => first + " " + second);
foreach (var item in numbersAndWords)
Console.WriteLine(item);
Would look something like this:
var files = Directory.GetFiles(#".\GalleryImages");
string[] names = new string[] { "Matt", "Joanne", "Robert", "Andrei", "Mihai","Radu","Ionica","Vasile"};
var zipped = files.Zip(names, (f, n) => new { File = f, Name = n });
foreach(var fn in zipped)
Console.WriteLine(fn.File + " " + fn.Name);
But I haven't tested this one.
It's not clear what you're asking. But, you can't iterate two iterators with foreach; but you can increment another variable in the foreach body:
int i = 0;
foreach(var file in files)
{
var name = names[i++];
// TODO: do something with name and file
}
This, of course, assumes that files and names are of the same length.
You can't. Use a for loop instead.
for(int i = 0; i < files.Length; i++)
{
var file = files[i];
var name = names[i];
}
If the both array have the same length this should work.
You have two options here; the first works if you are iterating over something that has an indexer, like an array or List, in which case use a simple for loop and access things by index:
for (int i = 0; i < files.Length && i < names.Length; i++)
{
var file = files[i];
var name = names[i];
// Do stuff with names.
}
If you have a collection that doesn't have an indexer, e.g. you just have an IEnumerable and you don't know what it is, you can use the IEnumerable interface directly. Behind the scenes, that's all foreach is doing, it just hides the slightly messier syntax. That would look like:
var filesEnum = files.GetEnumerator();
var namesEnum = names.GetEnumerator();
while (filesEnum.MoveNext() && namesEnum.MoveNext())
{
var file = filesEnum.Current;
var name = namesEnum.Current;
// Do stuff with files and names.
}
Both of these assume that both collections have the same number of items. The for loop will only iterate as many times as the smaller one, and the smaller enumerator will return false from MoveNext when it runs out of items. If one collection is bigger than the other, the 'extra' items won't get processed, and you'll need to figure out what to do with them.
I guess the files array and the names array have the same indices.
When this is the case AND you always want the same index at one time you do this:
for (int key = 0; key < files.Length; ++key)
{
// access names[key] and files[key] here
}
You can try something like this:
var pairs = files.Zip(names, (f,n) => new {File=f, Name=n});
foreach (var item in pairs)
{
Console.Write(item.File);
Console.Write(item.Name);
}

How to create mutlidimensional list for this in C#?

I got a table (in file) which I split into blocks by spaces.
I need structure like this:
-----------------------------
|21|22|23|33|3323|
|32|32|
|434433|545454|5454|
------------------------------
It's more like each row is its own table. How should I do this?
I tried List<List<string>> matrix = new List<List<string>>(); but I can't seem to find a way to work with it.
EDIT - can someone tell me what's wrong with this code???? Matrix[0][0] is same as matrix [1][0].. it seems that same row is added to matrix all the time, but I clear it ...
static ArrayList ReadFromFile(string filename)
StreamReader SR;
string S;
string[] S_split;
SR = File.OpenText(filename);
S = SR.ReadLine();
ArrayList myItems = new ArrayList();
List<List<string>> matrix = new List<List<string>>();
List<string> row = new List<string>();
while (S != null)
{
row.Clear();
S_split = S.Split(' ');
for (int i = 1; i < S_split.GetLength(0); i++)
{
row.Add(S_split[i]);
matrix.Add(row);
}
S = SR.ReadLine();
}
Console.WriteLine(matrix[1][1]);
SR.Close();
return myItems;
}
Not sure if I understand this correctly.
List<List<int>> table = new List<List<int>>();
List<int> row = new List<int>();
row.Add(21);
row.Add(22);
row.Add(23);
row.Add(33); // and so on
table.Add(row);
row = new List<int>();
row.Add(1001);
row.Add(1002);
table.Add(row);
MessageBox.Show(table[0][3].ToString());
The program should show a message box with text "33".
You should be able to work with it as you'd expect to deal with a list within a list.
matrix.Add(new List<string>);
matrix[0].Add("a string");
List<List<String>> matrix = new List<List<String>>();
foreach (String line in file)
{
String[] values = line.Split(new Char[] { ' ' });
matrix.Add(new List<String>(values));
}
Just iterate through your file and for every line do the following.
Generate a new List
Fill it with the data for the line
Add the list for the current line to your list for the complete file
Note that foreach (String line in file) is just pseudo code. Further you can merge the to lines in the body to a single line.
matrix.Add(new List<String>(line.Split(new Char[] { ' ' })));
You're describing a jagged array. I'm not exactly sure if a List won't be overkill? If you just have to import the data from the file and than use it, a jagged array should be simple enough.
Example:
int[][] jaggedArray = new int[][]
{
new int[] {21, 22, 23, 33, 3323},
new int[] {32, 32},
new int[] {434433, 545454, 5454}
};
you can also buildup the jagged array in a loop while processing your file, like this:
int[][] result = new int[numberOfLines][];
for (int currentLine = 0; currentLine < numberOfLines; currentLine++)
{
String line = fileStream.ReadLine();
int[] values = SplitAndConvertLine(line);
result[currentLine] = values;
}
If you are trying to read from the file then try something like the following (Note the following code has not been run through a compiler)
List<string[]> matrix = new List<string[]>();
while(!instream.EndOfStream)
{
var values = instream.ReadLine().Split(new[] {' '});
matrix.Add(values);
}

Categories

Resources