After accessing the local file, I need to check and add the missing column (walmart) before converting it to xml. I confirm data is available in the csv file.
Currently I am getting an error
System.InvalidOperationException: 'Collection was modified; enumeration operation may not execute
Code:
string[] vs = File.ReadAllLines(#"C:/Users/Raw.csv");
var lines = new List <String>();
lines = vs.ToList();
foreach (var check in lines)
{
if (!check.Contains("Walmart"))
{
lines.Insert(0,"Walmart");
}
}
foreach (var shw in lines)
{
Console.WriteLine(shw);
}
Techically, if you want just amend your current code you can count how many Walmarts we should add:
var lines = File
.ReadLines(#"C:/Users/Raw.csv")
.ToList();
int walmartsToAdd = 0;
foreach (var check in lines)
if (!check.Contains("Walmart"))
walmartsToAdd += 1;
if (walmartsToAdd > 0)
lines.InsertRange(0, Enumerable.Repeat("Walmart", walmartsToAdd));
foreach (var shw in lines)
Console.WriteLine(shw);
But it seems, that you should modify lines: abc,def => Walmart,abc,def. If it's your case you can just add Select
var lines = File
.ReadLines(#"C:/Users/Raw.csv")
.Select(line => line.StartsWith("Walmart,") ? line : $"Walmart,{line}")
.ToList();
foreach (var shw in lines)
Console.WriteLine(shw);
You can't modify the source Enumerable while iterating on it. I always imagine that the enumerator has inside a current index and if for example, the change would delete all the members the index wouldn't make any sense anymore. The easy solution is to iterate on something else / make a copy.
Here instead of lines you can try iterating on the variable 'vs'.
var vs = File.ReadAllLines(#"C:/Users/Raw.csv");
var lines = vs.ToList();
foreach (var check in vs)
{
if (!check.Contains("Walmart"))
{
lines.Insert(0, "Walmart");
}
}
foreach (var shw in lines)
{
Console.WriteLine(shw);
}
Related
I have a file with "Name|Number" in each line and I wish to remove the lines with names that contain another name in the list.
For example, if there is "PEDRO|3" , "PEDROFILHO|5" , "PEDROPHELIS|1" in the file, i wish to remove the lines "PEDROFILHO|5" , "PEDROPHELIS|1".
The list has 1.8 million lines, I made it like this but its too slow :
List<string> names = File.ReadAllLines("firstNames.txt").ToList();
List<string> result = File.ReadAllLines("firstNames.txt").ToList();
foreach (string name in names)
{
string tempName = name.Split('|')[0];
List<string> temp = names.Where(t => t.Contains(tempName)).ToList();
foreach (string str in temp)
{
if (str.Equals(name))
{
continue;
}
result.Remove(str);
}
}
File.WriteAllLines("result.txt",result);
Does anyone know a faster way? Or how to improve the speed?
Since you are looking for matches everywhere in the word, you will end up with O(n2) algorithm. You can improve implementation a bit to avoid string deletion inside a list, which is an O(n) operation in itself:
var toDelete = new HashSet<string>();
var names = File.ReadAllLines("firstNames.txt");
foreach (string name in names) {
var tempName = name.Split('|')[0];
toDelete.UnionWith(
// Length constraint removes self-matches
names.Where(t => t.Length > name.Length && t.Contains(tempName))
);
}
File.WriteAllLines("result.txt", names.Where(name => !toDelete.Contains(name)));
This works but I don't know if it's quicker. I haven't tested on millions of lines. Remove the tolower if the names are in the same case.
List<string> names = File.ReadAllLines(#"C:\Users\Rob\Desktop\File.txt").ToList();
var result = names.Where(w => !names.Any(a=> w.Split('|')[0].Length> a.Split('|')[0].Length && w.Split('|')[0].ToLower().Contains(a.Split('|')[0].ToLower())));
File.WriteAllLines(#"C:\Users\Rob\Desktop\result.txt", result);
test file had
Rob|1
Robbie|2
Bert|3
Robert|4
Jan|5
John|6
Janice|7
Carol|8
Carolyne|9
Geoff|10
Geoffrey|11
Result had
Rob|1
Bert|3
Jan|5
John|6
Carol|8
Geoff|10
In C# windows application, I am comparing two different string arrays and depending on which array size is big, I add or delete items to a list view box. using the below code I am able to add to list view without any issues, but I am not able to remove from it.
I get an error that says.
"Error CS1503, Argument 1: cannot convert from 'string' to 'System.Windows.Forms.ListViewItem'"
Here is an excerpt from my code
string[] currentFilesList = GetFileList();
if (currentFilesList.Length > prevFilesList.Length)
{
var addedList = currentFilesList.Except(prevFilesList).ToArray();
foreach (var item in addedList)
{
listView1.Items.Add(item);
}
}
if (currentFilesList.Length < prevFilesList.Length)
{
var removedList = prevFilesList.Except(currentFilesList).ToArray();
foreach (string item in removedList)
{
listView1.Items.Remove(item); //I get error here on "item" Argument 1: cannot convert from 'string' to 'System.Windows.Forms.ListViewItem'"
}
}
prevFilesList = currentFilesList;
I tried both string and var but same result.
you can remove item by
foreach (string item in removedList)
{
var toRemove =listView1.Items.Find(item);
if (toRemove != null)
{
listView1.Items.Remove(toRemove);
}
}
or you can use RemoveByKey
foreach (string item in removedList)
{
listView1.Items.RemoveByKey(item);
}
You can try this by using linq
var newlist = listView1.Cast<ListViewItem>().Where(p=>p.Text.Contains("OBJECT")).ToList().ForEach(listBox1.Items.Remove);
I've created a regex pattern which finds all #REF in my excel file. I've created a foreach loop to return all the #REF and siplay them in the console along with a count of them. This works fine. However I then created a foreach loop to remove all the #REF references but it only removes one each time I run the project. I've debugged this and after Regex finds the match once in the if statement the next time it enters into the foreach it skips the if statement as if it can't find another match. I'm not sure why this is
My code is as fallows
Code to return all the #ref values
using (var spreadsheet = DocumentFormat.OpenXml.Packaging.SpreadsheetDocument.Open(#"C:\Users\Craig\Desktop\newTest.xlsx", true))
{
var workbook = spreadsheet.WorkbookPart;
Workbook w = new Workbook();
var names = workbook.Workbook.DefinedNames;
var work = workbook.Workbook;
System.Text.RegularExpressions.Regex regex = new System.Text.RegularExpressions.Regex(#"#REF");
int count = result.InactiveNamedRangeCount = names.Count(n => regex.IsMatch(n.InnerText));
Console.WriteLine(count);
foreach (var name in names)
{
if (regex.IsMatch(name.InnerText))
{
Console.WriteLine(name.InnerText);
}
}
Code to delete each #REF value
foreach (var name in names)
{
if (regex.IsMatch(name.InnerText))
{
name.Remove();
work.Save();
}
}
Console.WriteLine(count);
Console.ReadKey();
}
The solution to the problem was I needed to add a ToList to my names variable.
foreach (var name in names.ToList())
{
if (regex.IsMatch(name.InnerText))
{
name.Remove();
work.Save();
}
}
I am using this foreach loop to search for files in a directory and then read them.
foreach (string file in Directory.EnumerateFiles(location, "*.MAI"))
Inside this loop I want to search for the line in the file that contains the word "Sended". Is there a way to look for this word and then read that line?
Try it:
var location = #"<your location>";
foreach (string file in Directory.EnumerateFiles(location, "*.MAI"))
{
var findedLines = File.ReadAllLines(file)
.Where(l => l.Contains("Sended"));
}
If you work with big files, you should use ReadLines method, because when you use ReadLines, you can start enumerating the collection of strings before the whole collection is returned; when you use ReadAllLines, you must wait for the whole array of strings be returned before you can access the array.
Another example from msdn:
var files = from file in Directory.EnumerateFiles(location, "*.MAI")
from line in File.ReadLines(file)
where line.Contains("Sended")
select new
{
File = file,
Line = line
};
Full information, look here: https://msdn.microsoft.com/library/dd383503.aspx
If .MAI files are Textfiles try the following:
foreach (string file in Directory.EnumerateFiles(location, "*.MAI"))
{
foreach (string Line in File.ReadAllLines(file))
{
if (Line.Contains("Sended"))
{
//Do your stuff here
}
}
}
I have an 'foreach';
foreach (var item in Model.LstUnidadesGerenciais)
{
var count = Model.LstUnidadesGerenciais.Count;
}
I need to get count with one condition like this:
foreach (var item in Model.LstUnidadesGerenciais)
{
if (item.Level == 1)
{
var count = Model.LstUnidadesGerenciaisWITHCONDITION.Count;
}
}
I think this is simple, but I'm very begginer in C#
Thank you!
Using Linq
var cnt = Model.LstUnidadesGerenciais.Count(x=>x.Level==1);
You can use LINQ Where to select items matching criteria (Level == 1):
var count = Model.LstUnidadesGerenciais.Where(i => i.Level == 1).Count();
Use Count method of LINQ -
var count = Model.LstUnidadesGerenciais.Count(i => i.Level == 1);
In the first example, you don't need the foreach loop. You can tell, because you never use the item, you use the collection instead. I think you need to understand what foreach does here:
foreach (var item in Model.LstUnidadesGerenciais)
{
var count = Model.LstUnidadesGerenciais.Count;
}
foreach will iterate over Model.LstUnidadesGerenciais. This means that for every item in Model.LstUnidadesGerenciais, the code inside the curly brackets is executed, with var item containing the current item of the collection. See MSDN for detailed information
As for the second example: You need a variable that contains a number. In the foreach loop you can increment the variable like:
int count = 0;
foreach (var item in Model.LstUnidadesGerenciais)
{
if (item.Level == 1)
{
count++;
}
}