C# if else conditional inside of foreach loop possibly using count - c#

I have working example without the conditional here.
public string RenderPostTags(DMCResultSet resultSet)
{
string output = "";
string filterForm = RenderFilterForm(resultSet);
string pagination = RenderPagination(resultSet);
List<XElement> items = resultSet.items;
foreach(XElement i in items)
{
string tags = "";
if (i.Element("tags") != null)
{
foreach(string tag in i.Element("tags").Elements("tag"))
{
tags += "" + tag + "";
}
}
output += tags;
}
return output;
}
I know just putting a count on it wont work but I've tried several different methods and they haven't worked for me. Could be a syntactical error I'm a total C# noob.
But I need to output adjusted html using a if else conditional similar to this
public string RenderPostTags(DMCResultSet resultSet){
string output = "";
string filterForm = RenderFilterForm(resultSet);
string pagination = RenderPagination(resultSet);
List<XElement> items = resultSet.items;
foreach(XElement i in items){
string tags = "";
if (i.Element("tags") != null) {
int count = 1;
int total = i.Element("tags").Elements("tag").Count;
foreach(string tag in i.Element("tags").Elements("tag")) {
if(count == total){
tags += "" + tag + "";
count++;
}else{
tags += "" + tag +","+ " " + "";
count++;
}
}
}
output += tags;
}
return output;
}
Methods I have tried can be found on this thread.
Foreach loop, determine which is the last iteration of the loop
Thank you for any assitance.

As #Sach said, use the for loop instead of foreach.
string output = "";
List<XElement> items = new List<XElement>();
foreach (XElement i in items)
{
string tags = "";
if (i.Element("tags") != null && i.Element("tags")?.Elements("tag") != null)
{
List<XElement> tagItems = i.Element("tags").Elements("tag").ToList();
if (tagItems == null) continue;
for (int j = 0; j < tagItems.Count(); j++)
{
XElement tag = tagItems[j];
if (j == i.Element("tags")?.Elements("tag").Count() - 1)
{
tags += "" + tag + "";
}
else
{
tags += "" + tag + "," + " " + "";
}
}
}
output += tags;
}

You can write your foreach loop like this to capture both conditions. You can use condition ? true : false to write either/or based on the last item in the collection.
int counter = 1; // Start with 1 since we are using != later on.
int totalRecords = i.Element("tags").Elements("tag").Count();
foreach (string tag in i.Element("tags").Elements("tag"))
tags += "" + tag + counter++ != totalRecords ? ", " : string.Empty + "";
Above is equivalent to
if (i.Element("tags") != null)
{
int counter = 1;
int totalRecords = i.Element("tags").Elements("tag").Count();
foreach (string tag in i.Element("tags").Elements("tag"))
{
if (counter++ == totalRecords)
{
tags += "" + tag + "";
}
else
{
tags += "" + tag + ", " + "";
}
}
}
Make a note that IEnumerable does not have a Count property but have a method Count().

So maybe for namespace reasons the count method would not solve my issue.
However after some toil this solution worked perfectly. Thankyou for those to helped me get to this solution.
public string RenderPostTags(DMCResultSet resultSet){
string output = "";
string filterForm = RenderFilterForm(resultSet);
string pagination = RenderPagination(resultSet);
List<XElement> items = resultSet.items;
foreach(XElement i in items){
string tags = "";
if (i.Element("tags") != null) {
foreach(string tag in i.Element("tags").Elements("tag")){
if(tags != "") tags += ", ";
tags += "" + tag +"";
}
}
output += tags;
}
return output;
}

Related

StringReader not "exiting"/breaking

I am experiencing a problem with the below code… When I run it the code never exits. I have tried to debug this for about an hour and I am at a complete loss as to what the problem is. OutputDebug(); is essentially like Console.WriteLine();
//Iterate through all lines to find sections
using (StringReader lineReader = new StringReader(Program))
{
int i = 0;
string line = string.Empty;
while (line != null)
{
line = lineReader.ReadLine();
if (line != string.Empty)
{
//If the program is exiting (doExit == true), then break the lööp bröther
if (doExit)
break;
//Iterate through all characters in the line
foreach (char Character in line)
{
i++;
OutputDebug(i.ToString());
if (isOnSameLineAsSectionStart)
{
sectionName += Character;
}
else if (Character == ':' && sectionName == string.Empty)
{
isOnSameLineAsSectionStart = true;
}
else if (Character == ':' && !isOnSameLineAsSectionStart && sectionName != string.Empty)
{
OutputDebug("End of section \"" + sectionName + "\" found");
OutputDebug(linesInSection.Count() + " lines found total in " + sectionName + "\" during section search");
try
{
sections.Add(sectionName, linesInSection);
}
catch (Exception)
{
OutputError("Two/Multiple sections with the same names exist. Ignoring the latest section with the same name");
}
linesInSection = new List<string>();
sectionName = string.Empty;
isOnSameLineAsSectionStart = true;
}
}
if (!isOnSameLineAsSectionStart && sectionName != string.Empty)
{
linesInSection.Add(line);
}
if (isOnSameLineAsSectionStart && sectionName != string.Empty)
{
OutputDebug("Start of section \"" + sectionName + "\" found");
}
if (isOnSameLineAsSectionStart == true)
{
isOnSameLineAsSectionStart = false;
}
}
lineReader.Close();
OutputDebug("In StringReader!" + i);
}
Thanks in advance!
you can use while approach below:
while ((line = reader.ReadLine()) != null)
{
foreach (char Character in line)
{
i++;
OutputDebug(i.ToString());
}
}
Well, if you want to output all the characters line by line. You could split them into an array of strings:
var lines = Regex.Split(input, "\r\n|\r|\n") extracted from here.
Later, using a foreach instead of a while statment you should solve the problem:
foreach(string line in lines)
Also comparing a string to a null value... Doesn't look so fine. Why don't use (in-built) string.IsNullOrEmpty(line) method to check if the current line is null?
If you want to use your approach you should do something like this:
while (!string.IsNullOrEmpty(line = reader.ReadLine()))
{
// Your code...
}
Hope this helps!
Since we're limited to this snippet we can only make assumptions.
lineReader.ReadLine();
if this is a blocking call than the code may never exit as long as no input is given.
if this is a unblocking call, it means that it returns something even though no input is provided. If returned value is empty string in this case then you're in infinite loop.
I believe the key function is ReadLine here.

how to copy multiple line from text file C#

I need to copy multiple lines from text file(cisco config file): based on the below condition
if the line starts with interface copy from interface until '! '
my file is like :
!
access-list 1>
!
interface 1
ip address xx.xx.xx.xx
!
interface 2
ip address xx.xx.xx.xx
!
route 1
!
I try the below code :
var lines = File.ReadAllLines("C:\\My File2.txt");
foreach (var line1 in lines){
string firstWord = line1.Split(' ').First();
if ((firstWord == "access-list") && (!line1.Contains("remark ")))
{
TextBox1.Text = TextBox1.Text + "\r\n" + line1;
}
else if (firstWord == "nat")
{
TextBox2.Text = TextBox2.Text + "\r\n" + line1;
}
else if (firstWord == "interface")
{
var result = lines.Substring(line1.LastIndexOf('!') + 1);
TextBox3.Text = TextBox3.Text + "\r\n" + result;
}
but I get only one line as output
In case you want to keep your algorithm, this will work for you.
var lines = File.ReadAllLines("C:\\My File2.txt");
int i;
for (i = 0; i<lines.Length;i++)
{
var line1 = lines[i];
if (line1 == "!" || line1 == " ") continue;
if (line1.StartsWith("access-list")) && (!line1.Contains("remark ")))
{
TextBox1.Text = TextBox1.Text + "\r\n" + line1;
}
else if (line1.StartsWith("nat"))
{
TextBox2.Text = TextBox2.Text + "\r\n" + line1;
}
if (line1.StartsWith("interface"))
{
var str = line1;
while (!Equals(lines[i + 1], "!"))
{
str += lines[i + 1];
i++;
}
TextBox3.Text = TextBox3.Text + "\r\n" + str;
}
}
As per the file structure shown by you interface and ip address are on different lines. So you won't get it in same iteration of for loop. When you find that firstWord == "interface" you will need to set a flag that will tell you that next line is ip address and in next iteration check if that flag is true parse the current line as ip address and process it the way you want.
You should use "File.ReadAllText" instead of "File.ReadAllLines". "File.ReadAllText" returns a string with the complete text file text. After that, you can use the "String.Split" method to generate a string array.
var lines = File.ReadAllText("C:\\My File2.txt");
var seperatedStrings = lines.Split('!');
Each index of "seperatedStrings" contains what you want.
UPDATE: Here is a code snippet, that can help:
var lines = File.ReadAllText("C:\\My File2.txt");
var seperatedStrings = lines.Split('!');
foreach (var oneString in seperatedStrings)
{
if (oneString.Contains("access-list"))
{
Console.WriteLine("Access-List: " + oneString);
}else if (oneString.Contains("nat"))
{
Console.WriteLine("Nat: " + oneString);
}else if (oneString.Contains("interface"))
{
Console.WriteLine("Interface: " + oneString);
}
}
This is the output of my code snippet:

IndexOutOfRangeException while adding text to String

My programs adds two arrays into a part of a string using a while loop
ex:
hnames[0] = user
hvals[0] = admin
transformed into: user=admin&
I get IndexOutOfRangeException and i don't know how to fix it.
string[] hnames = names.ToArray(typeof(string)) as string[];
string[] hvals = values.ToArray(typeof(string)) as string[];
String postData = "";
//Loops through the arrays and put data into postData var
while (i < hnames.Length)
{
i++;
int end = hnames.Length;
end--;
if (!(i == end))
{
postData = postData + hnames[i] + "=" + hvals[i] + "&"; //IndexOutOfRangeException here
}
else
{
postData = postData + hnames[i] + "=" + hvals[i];
}
}
You're incrementing i before using it, so at the end of the loop, when i = hnames.Length - 1, the i++; at the start of the loop sets i = hnames.Length, which is over the end of the array. You're also skipping i = 0, in effect.
Move i++; down to the end of the loop.
I just wanted to show you a simplified version of your logic with the foreach as suggested by others. Number of lines may be same but I think this is easy to read.
string[] hnames = names.ToArray(typeof(string)) as string[];
string[] hvals = values.ToArray(typeof(string)) as string[];
string postData = string.Empty;
bool isFirst = true;
int i = 0;
/* Assumption - Both arrays hnames and hvals are of same length.
Otherwise you'll get the same error if hvals.Length < hnames.Length even if you use the foreach
*/
foreach (string hname in hnames)
{
if (isFirst)
{
postData = hname + "=" + hvals[i] + "&"; //IndexOutOfRangeException here
isFirst = false;
}
else
{
postData += hname + "=" + hvals[i];
}
i++;
}

Taglib array exception when setting Artist field

I keep getting an array out of bounds exception with Taglib.tag.Performers in this function that edits ID3 data. I read elsewhere that clearing tag.performers[] can help (if null) but I still get the error sometimes.
Error message:
"Index was outside the bounds of the array.Data:
'System.Collections.ListDictionaryInternal' for test.mp3"
var fileArr = Directory.GetFiles(BasePath, "*.*", SearchOption.AllDirectories).Where(s => s.EndsWith(".mp3") || s.EndsWith(".m4a")).ToArray();
foreach (var file in fileArr)
{
string fileName = Path.GetFileName(file);
string tagArtist = "";
string tagTitle = "";
string tempRegFilename = fileName;
string title = "";
//Apply to tag
TagLib.File mp3tag = TagLib.File.Create(file);
if (mp3tag.Tag.Title != null && mp3tag.Tag.Title.Length > 1)
{
title = mp3tag.Tag.Title;
}
else
{
mp3tag.Tag.Title = String.Empty;
}
if (mp3tag.Tag.Performers[0].Length < 1 || mp3tag.Tag.Performers[0] == null)
{
mp3tag.Tag.Performers[0] = null;
mp3tag.Tag.Performers = new[] { String.Empty };
mp3tag.Save();
}
if (mp3tag.Tag.Performers[0].Length > 1)
{
string[] performers = mp3tag.Tag.Performers;
if (title.Length > 2 && performers[0].Length > 1)
{
tagTitle = title;
tagArtist = performers[0].ToString();
Log.Info("ID3 Artist: " + "[" + tagArtist + "]");
Log.Info("ID3 Title: " + "[" + tagTitle + "]");
Log.Info("Tag data OK");
}
}
//Get artist from filename
if (mp3tag.Tag.Performers[0].Length < 1 || mp3tag.Tag.Performers == null)
{
mp3tag.Tag.Performers = new[] { String.Empty };
string prevArtist = String.Empty;
if (tempRegFilename.Contains("-"))
{
Log.Info("Artist data missing...");
string[] words = tempRegFilename.Split('-');
{
words[0] = words[0].Trim();
string perf = words[0];
mp3tag.Tag.Performers = new[] { perf };
Log.Info("Artists changed from \'" + prevArtist + "\' to " + "'" + perf + "'" + "\r\n");
mp3tag.Save();
}
}
mp3tag.Save();
}
}
catch (Exception ex)
{
Log.Error("TAG EXCEPTION: " + ex.Message + "Data: " + "'" + ex.Data + "'" + " for " + fileName + "\r\n" + ex.HelpLink);
}
Can anyone see what's wrong? I don't have much experience and could use the help. Thanks.
You seem to be assuming in a number of places that mp3Tag.Tag.Performers will have at least one element in it. If it doesn't, then you'll get the exception that you mention whenever you try to access mp3tag.Tag.Performers[0]
It looks like you may be trying to catch that possibility with this code:
if (mp3tag.Tag.Performers[0].Length < 1 || mp3tag.Tag.Performers[0] == null)
{
mp3tag.Tag.Performers[0] = null;
mp3tag.Tag.Performers = new[] { String.Empty };
mp3tag.Save();
}
But your logic is incorrect: you're getting the first element from the array (apparently a string) and checking its length, instead of checking the length of the array itself. Try this:
if (mp3tag.Tag.Performers.Length < 1 || mp3tag.Tag.Performers[0] == null)
{
mp3tag.Tag.Performers = new[] { String.Empty };
mp3tag.Save();
}
PS: It'll be much easier for you to see where your errors are if your log includes the stack trace of the exception, rather than just its message. I typically find it best to just use the ToString() on the exception itself.

How to remove missing tags from HTML source in Asp.net

Sometime it has been seen that the HTML source that we receive from some website are not having proper tag ending, and that affect our UI.
So, like
<br /><p>hello the para start here </p> <p>some text and no ending tag
And there is no ending tag .
I want to retain the HTML format and want this like
<br /><p>hello the para start here </p> some text and no ending tag
One more thing is that sometimes we get the end tag at the start that should also be resolved by the algorithm.
Hey guys I thought for a long time and finally I have code for my problem, i am posting it here so that other can get benefit from this ....
public static string RemoveIncompleteTags(string source, string tag)
{
source = source.Replace(" ", " ");
source = source.Replace("/n", string.Empty).Replace("/r", string.Empty).Replace("/t", string.Empty);
source = source.Replace("<" + tag + "></" + tag + ">", string.Empty);
source = source.Replace("<" + tag + "> </" + tag + ">", string.Empty);
source = source.Replace("<" + tag + "> </" + tag + ">", string.Empty);
Dictionary<int, string> oDict = new Dictionary<int, string>();
string[] souceList;
Dictionary<int, string> final = new Dictionary<int, string>();
bool opening = false;
bool operate = false;
source = source.Replace(" ", " ");
source = source.Replace(">", "> ").Replace("<", " <");
source = source.Replace(" >", ">").Replace("< ", "<");
source = source.Replace(" ", " ").Replace(" ", " ");
souceList = source.Split(' ');
for (int i = 0; i < souceList.Length; i++)
{
string word = souceList[i];
if (word.ToLower() == "<" + tag.ToLower() + ">")
{
opening = true;
operate = true;
}
else if (word.ToLower() == "</" + tag.ToLower() + ">")
{
opening = false;
operate = true;
}
if (operate)
{
if (opening)
{
oDict.Add(i, word);
final.Add(i, word);
}
else
{
if (oDict.Count != 0)
{
oDict.Remove(oDict.Last().Key);//.ToList().RemoveAt(oDict.Count - 1);
final.Add(i, word);
}
else
{
// need not to add to the output string
// code if you want to log
}
}
operate = false;
opening = false;
}
else
{
final.Add(i, word);
}
}
if (final.Count > 0)
{
if (oDict.Count > 0)
{
foreach (var key in oDict.Keys)
{
final.Remove(key);
}
}
StringBuilder fText = new StringBuilder();
final.ToList().ForEach(wd =>
{
if (wd.Value.Trim().Length > 0)
fText.Append(wd.Value.Trim() + " ");
});
return fText.ToString().Trim();
}
else
{
return string.Empty;
}
}
thanks...

Categories

Resources