Loop only fires once - c#

Hi guys i am reading a file containing playlists.
(Rows of mp3 file locations)
I currently have the format ( name ; c:\song.mp3 ; c:\song.mp3 ; c:\song.mp3 ; c:\song.mp3 etc etc)
There are many rows of these in the file.
I have tried both foreach loops and for loops to try and solve this (as shown below)
string[] lines = File.ReadAllLines("playlists.txt");
MessageBox.Show(lines.Count().ToString());
for (int y = 0; y <= lines.Count(); y++)
{
string[] res = lines[y].Split(';');
for (int x = 0; x <= res.Count(); x ++)
{
if (x == 0) { currentPlaylist = new Playlist(res[x]); }
else { currentPlaylist.Add(new MP3(res[x])); }
}
}
But for some reason it will only loop once (I have replaced the outer loop with a foreach which had the same result.
even if the lines.Count() shown in the messagebox shows a number greater then 1
I'm sure once this is solved it must be basic mistake but Im lost
Thanks
EDIT* this is the file dont know how this will help...
Library;C:\Users\Blah\Desktop\Iphone Music\Queens of the Stone Age - If I Had A Tail.mp3
playlist1;C:\Users\Blah\Desktop\Iphone Music\Red Hot Chili Peppers - Can t Stop.mp3;C:\Users\Blah\Desktop\Iphone Music\Red Hot Chili Peppers - Otherside .mp3
playlist2;C:\Users\Blah\Desktop\Iphone Music\Red Hot Chili Peppers - Otherside .mp3;C:\Users\Blah\Desktop\Iphone Music\Foo Fighters - Best Of You.mp3
playlist3;C:\Users\Blah\Desktop\Iphone Music\Red Hot Chili Peppers - Otherside.mp3;C:\Users\Blah\Desktop\Iphone Music\Foo Fighters - The Pretender.mp3
playlist4;C:\Users\Blah\Desktop\Iphone Music\Foo Fighters - Everlong.mp3;C:\Users\Blah\Desktop\Iphone Music\Foo Fighters - My Hero.mp3;C:\Users\Blah\Desktop\Iphone Music\I Am Giant - City Limits.mp3
I put it in as code so it would be easier to read
The only issue i am having is that the inner loop only fires once and i am unsure as to why.
Something in the following ....
for (int x = 0; x <= res.Count(); x ++)
{
if (x == 0) { currentPlaylist = new Playlist(res[x]); }
else { currentPlaylist.Add(new MP3(res[x])); }
}
is causing the outer loop to only fire once no matter the amount of lines in the code, if i remove the inner loop the outer loop loops the expected amount of times

Based on your question and comments you wrote, I think you are looking for something like:
// This method read the file and populate a List of Playlist.
// Each PlayList contain a list of MP3 songs
public List<Playlist> GetPlayLists()
{
// read all lines from the text file
string[] lines = File.ReadAllLines(#"c:\Temp\playlists.txt");
// declare a playlists variable to hold all the playlists and their songs
var playlists = new List<Playlist>();
// Loop through all the playlists (each line in the text file represents a playlist)
for (int plIdx = 0; plIdx < lines.Length; plIdx++)
{
// split in order to fins all the MP3 songs
string[] res = lines[plIdx].Split(';');
// create a new playlist (its name is passed into the constructor)
var playlist = new Playlist(res[0]);
// loop the songs (starting from index 1 since index=0 is the playlist name)
for (int songIdx = 1; songIdx < res.Length; songIdx++)
{
// Add to the playlist each song
playlist.Add(new MP3(res[songIdx]));
}
playlists.Add(playlist);
}
return playlists;
}
// Play list class containing all the MP3 songs (each line in text file)
class Playlist
{
public List<MP3> SongList { get; private set; }
public string Name { get; private set; }
public Playlist(string name)
{
Name = name;
SongList = new List<MP3>();
}
public void Add(MP3 mp3)
{
SongList.Add(mp3);
}
}
// MP3 Song class
class MP3
{
public string Location { get; private set; }
public MP3(string location)
{
Location = location;
}
}
This is how your playlists variable looks like after it has been populated with your playlists.txt file:
Do the following steps in order to make it work. Once working, you will have a reference so you can simply merge it into your existing project.
Create a new Console Application
Your class program:
class Program
{
static void Main(string[] args)
{
// FileReader is the class that contains the method that read from the playlists.txt file
var filereader = new FileReader();
var playlists = filereader.GetPlayLists();
}
}
Create a FileReader class and put the GetPlayLists method into
class FileReader
{
// This method read the file and populate a List of Playlist.
// Each PlayList contain a list of MP3 songs
public List<Playlist> GetPlayLists()
{
// .....
}
}
Put the other classes PlayList and MP3.
Now you should be able to run it without any issues.

Your code should throw an exception, as far as I can see. You use <= in your loop conditions, but when x == res.Count() you can not access res[x], because the index must be between 0 and Count-1.
Try to replace <= by <, at least.
And don't use Count() on arrays. They have .Length property.

Assuming that what you posted is the file you're reading then each line contains a single file location of the mp3. After splitting each line with ';' you can safely assume that the 2nd entry of the new array is the file path.
string[] lines = File.ReadAllLines("playlists.txt"); // 100 lines
for (int y = 0; y < lines.Length; y++) loops through array index 0 to 99
{
string[] res = lines[y].Split(';'); // lines[y] should be something like c:\song.mp3 ; c:\song.mp3 ; c:\song.mp3
// res[0] = Library
// res[1] = C:\Users\Blah\Desktop\Iphone Music\Queens of the Stone Age - If I Had A Tail.mp3
currentPlaylist = new Playlist(res[0].Trim());
currentPlaylist.Add(new MP3(res[1].Trim()));
}
Or if each line has multiple file paths..
string[] lines = File.ReadAllLines("playlists.txt"); // 100 lines
for (int y = 0; y < lines.Length; y++) loops through array index 0 to 99
{
string[] res = lines[y].Split(';'); // lines[y] should be something like c:\song.mp3 ; c:\song.mp3 ; c:\song.mp3
// res[0] = Library
// res[1] = C:\Users\Blah\Desktop\Iphone Music\Queens of the Stone Age - If I Had A Tail.mp3
currentPlaylist = new Playlist(res[0].Trim()); // res[0] is the playlist name right?
for(int x = 1; x < res.Length; x++)
{
currentPlaylist.Add(new MP3(res[x].Trim()));
}
}

Try this, you should not initialise currentPlayList in the inner loop as it will get reinitialised every time it loops through y
Playlist currentPlaylist;
string[] lines = File.ReadAllLines("playlists.txt");
for (int y = 0; y < lines.Length; y++)
{
if (y == 0) {
currentPlaylist = new Playlist();
}
string[] res = lines[y].Split(';');
for (int x = 0; x < res.Length; x ++)
{
currentPlaylist.Add(new MP3(res[x]));
}
}
Your outer loop actually runs more than once, but because you reinitialise the playlist, the only state that is persisted at the end of the outer loop is the very last iteration, this giving the appearance of having run only once.

Related

C# Append at last line a character on all then one by one?

I'm making console c# app that actually takes all lines from text1 and append to it in the end of each line a text that is ".php?" or ".html? and these texts are also lines from text2, I want to print the first one in text2 in the end of each line in text1. Then take the second one in text2 and do the same Until it finishes text2?
Here's my code:
string[] resultConfig = File.ReadAllLines("keywords.txt");
string[] readParameters = File.ReadAllLines("param.txt");
for (int i = 0; i < readParameters.Length; i++)
{
for (int x = 0; x < resultConfig.Length ; x++)
{
resultConfig[x] = resultConfig[x] + readParameters[i];
Console.WriteLine(resultConfig[x]);
}
}
OUTPUT:
**
keyboards.php?.html?.asp?
karachi.php?.html?.asp?
keychain.php?.html?.asp?
in khobar.php?.html?.asp?
lebanon.php?.html?.asp?
lights.php?.html?.asp?
london.php?.html?.asp?
must have.php?.html?.asp?
**
**
WHAT IT SHOULD BE:
keyboards.php?
karachi.php?
keychain.php?
in khobar.php?
lebanon.php?
lights.php?
london.php?
must have.php?
keyboards.html?
karachi.html?
keychain.html?
in khobar.html?
lebanon.html?
lights.html?
london.html?
must have.html?
**
etc...
** KEYWORDS.TXT CONTAINS **
keyboards
karachi
keychain
in khobar
lebanon
lights
london
must have
** PARAM.TXT CONTAINS **
.php?
.asp?
.html?
Your problem is this line resultConfig[x] = resultConfig[x] + readParameters[i];. In this line you change your string in resultConfig[x] and since you're using a nested loop, this happens for every line in your *param.txt` file.
In order to write you desired result in the console try this code instead:
string[] resultConfig = File.ReadAllLines("keywords.txt");
string[] readParameters = File.ReadAllLines("param.txt");
for (int i = 0; i < readParameters.Length; i++)
{
for (int x = 0; x < resultConfig.Length ; x++)
{
string line = resultConfig[x] + readParameters[i];
Console.WriteLine(line);
}
}
You keep adding the parameter to the config and you should change the order of the loops and not change the value in the array.
Something like this:
string[] resultConfig = File.ReadAllLines("keywords.txt");
string[] readParameters = File.ReadAllLines("param.txt");
for (int x = 0; x < resultConfig.Length ; x++)
{
for (int i = 0; i < readParameters.Length; i++)
{
Console.WriteLine(resultConfig[x] + readParameters[i]);
}
}
It appears you want to save all these results in the resultConfig array, but you can't just add more items to an array than it was initialized with - you have to resize it first using Array.Resize(ref resultConfig, resultConfig.Length * readParameters.Length).
However, even then it will be a little tricky to append to the first set of items and then add new items for the additional parameters (it can be done if that's really necessary).
Instead I would create a new List<string> to save the results, and leave the initial arrays as they are:
string[] resultConfig =
{
"keyboards",
"karachi",
"keychain",
"in khobar",
"lebanon",
"lights",
"london",
"must have"
};
string[] readParameters = {".php?", ".html?", ".asp?"};
var allCombinations = new List<string>();
for (int i = 0; i < readParameters.Length; i++)
{
for (int x = 0; x < resultConfig.Length; x++)
{
allCombinations.Add(resultConfig[x] + readParameters[i]);
Console.WriteLine(resultConfig[x] + readParameters[i]);
}
}

C# WFA - How to make a string list sort in the same positions as a sorted integer list

I am trying to make a high score system for a quiz game I have made. I have got all the scores and their names to read in, sort the scores and put them in rich text boxes (one for scores, one for their names). After I used .Sort() on the integer list (scores), the scores were in the correct order but the names (string list) no longer matched up with the scores.
Here is my code:
public partial class frmhighScore : Form
{
public frmhighScore()
{
InitializeComponent();
this.StartPosition = FormStartPosition.CenterScreen;
this.Name = "High Score";
}
string[] contains;
string[] scorenames;
List<int> scores = new List<int>(){ };
List<string> names = new List<string>(){ };
private void highScore_Load(object sender, EventArgs e)
{
scores.Clear();
names.Clear();
scorenames = File.ReadAllLines(AppDomain.CurrentDomain.BaseDirectory + "scorenames.txt");
foreach (string line in scorenames)
{
gameClass.scorenames.Add(line);
}
for (int x = 0; x < gameClass.scorenames.Count(); x++)
{
contains = gameClass.scorenames[x].Split(':');
names.Add(contains[0]);
scores.Add(Convert.ToInt32(contains[1]));
}
scores.Sort();
scores.Reverse();
for (int a = 0; a < scores.Count; a++)
{
}
for (int y = 0; y < names.Count(); y++)
{
richTextBox1.Text += names[y];
richTextBox1.Text += Environment.NewLine;
}
for (int z = 0; z < scores.Count(); z++)
{
richTextBox2.Text += scores[z];
richTextBox2.Text += Environment.NewLine;
}
}
}
gameClass.scorenames is a string list in my class which is used to read in the details from the text file. All ofther variables are local.
richTextBox1 is for the names and richTextBox2 is for the scores
Here is a screenshot of what the form currently looks like:
Current high score form
And here is the text file that I am reading in from (scorenames.txt):
r:6
bob:10
So as you can see, the names are not matched up with the sorted scores
So my final question is, how would I make it so that the names (bob / r) match up with their scores r is 4, bob is 10?
Any help would be greatly appreciated, thanks.
I think you just need to re model your display entity to bundle both Name and Score together. You might need to change your code somewhat similar to below snippet (I haven't taken care of new line format though)
public class DisplayCard
{
public int Score { get; set; }
public string Name { get; set; }
}
List<DisplayCard> ScoreCard = new List<DisplayCard>();
for (int x = 0; x < gameClass.scorenames.Count(); x++)
{
contains = gameClass.scorenames[x].Split(':');
var name = contains[0];
var score = Convert.ToInt32(contains[1]);
ScoreCard.Add(new DisplayCard { Name = name, Score = score });
}
var sortedCard = ScoreCard.OrderBy(o => o.Score).ToList();
foreach (var card in sortedCard)
{
richTextBox1.Text += card.Name;
richTextBox2.Text += card.Score;
/* take care of new line logic*/
}
You might create objects for each player which includes their score. Then use LINQ to sort them by the score, which will then retain the association with their name: https://msdn.microsoft.com/en-us/library/bb534966.aspx

trouble reading and writing to a file c#

I am currently trying to take a file of words that are not in alphabetical, re-order the words so that they are in alphabetical order (I am trying to use a non-built in sort method), and then write the newly ordered list into a new txt file(one that must be created). For example, lets say there is only five words in the txt file that are as follows "dog bat apple rabbit cat". I would want the program to resort these in alphabetical order, and then create a txt file that saves that order. As of right now, the program will iterate through the txt file, but will not save the re-ordered list into the new txt file. What is saved into the new file is this... "System.Collections.Generic.List`1[System.String]"
Truth be told, I am not very savvy with c# yet, so i apologize if my structuring or coding is not very well. The original file that is un-ordered is called "jumbled english FILTERED.ALL.txt", and the file I am trying to write to is called "english FILTERED.ALL.txt".
static void Main(string[] args)
{
// declaring integer for minimum.
int min = 0;
// declare the list for the original file
List<string> LinuxWords = new List<string>();
List<string> lexicalOrder = new List<string>();
// read the text from the file
string[] lines = System.IO.File.ReadAllLines("jumbled english FILTERED.ALL.txt");
string line = string.Empty;
// seperate each word into a string
//foreach (string line in lines)
//{
//add each word into the list.
//LinuxWords.Add(line);
//}
for (int i = 0; i < lines.Length - 1; i++)
{
for (int j = i + 1; j < lines.Length; j++)
{
if (lines[i].Length < lines[j].Length)
{
min = lines[i].Length;
}
else
{
min = lines[j].Length;
}
for (int k = 0; k < min; k++)
{
if (lines[i][k] > lines[j][k])
{
line = lines[i].ToString();
lines[i] = lines[j];
lines[j] = line;
break;
}
else if (lines[i][k] == lines[j][k])
{
continue;
}
else
{
break;
}
}
}
}
for (int i = 0; i < lines.Length; i++)
{
Console.WriteLine("The program is formatting the correct order");
lexicalOrder.Add(lines[i]);
}
//lexicalOrder.ForEach(Console.WriteLine);
//}
//LinuxWords.ForEach(Console.WriteLine);
File.WriteAllText(AppDomain.CurrentDomain.BaseDirectory + "english FILTERED.ALL.txt",
lexicalOrder.ToString());
// write the ordered list back into another .txt file named "english FILTERED.ALL.txt"
// System.IO.File.WriteAllLines("english FILTERED.ALL.txt", lexicalOrder);
Console.WriteLine("Finished");
}
Assuming you mean that you don't get the list saved (if that's not the problem - please be more specific) - you need to change
lexicalOrder.ToString()
to something like
lexicalOrder.Aggregate((s1, s2) => s1 + " " + s2)

Splitting timespan when overlapping

I have multiple TXT files which represents time spans in seconds for selected portions of videos. For example, 1.23-5.45.
I want to use these time spans to take these portions of multiple videos and create a single video with all the portions.
I'm parsing all of these TXT files into an array of KeyValue pairs list:
List<KeyValuePair<Double, Double>>[] TagsOfSeconds= new List<KeyValuePair<Double, Double>>[]()
Each index of array element represents a TXT file. And each element is a a KeyValue pair list where each pair is the start-end of the seconds time span.
My requirement is to parse these TXT files and split the time spans to segments of 5 seconds (5 is an example, the segment value will be provided by the user) and order the segments with priority to segment with the smallest value (happened before other segments) and if two are equal, take the one that is first in the TagsOfSeconds array.
Here is an illustration. Segment order is what I'm trying to achieve:
I created the following structure to keep track of the portions parsed from the text files:
public struct PortionInfo
{
public Double Start, End;
public int VideoIndex, PortionIndex;
public Double PortionLength;
}
Here is my code for ordering the loaded segments based on the start time span and TXT file index:
private void OrderVideoPortions(List<KeyValuePair<Double, Double>>[] videoPortionslist)
{
videoPortionsOrder = new List<PortionInfo>(); //videoPortionsOrder.Sort()
for(int i=0;i< videoPortionslist.Length;i++)
{
for (int j = 0; j < videoPortionslist[i].Count; j++)
{
PortionInfo currentPortionInfo = new PortionInfo();
currentPortionInfo.VideoIndex = i;
currentPortionInfo.PortionIndex = j;
currentPortionInfo.Start = videoPortionslist[i][j].Key;
currentPortionInfo.End = videoPortionslist[i][j].Value;
currentPortionInfo.PortionLength = currentPortionInfo.End - currentPortionInfo.Start;
videoPortionsOrder.Add(currentPortionInfo);
}
}
videoPortionsOrder.Sort(SortAscending);
}
public static int SortAscending(PortionInfo p1, PortionInfo p2)
{
int returnVal = p1.Start.CompareTo(p2.Start);
if (returnVal == 0)
{
return p1.VideoIndex.CompareTo(p2.VideoIndex);
}
else
return returnVal;
}
Now I have to generate the segments from the sorted list.
Can any one help me please to achieve this? I just want help or guidance on determining the intersections and segments.
I modified the PortionInfo Structure to have constructor and a bool Active that is set automatically to true when the structure is created.
private void CreateFinalSegments(List<PortionInfo> orderedVideoPortions)
{
int segmentSize = int.Parse(_txtTimeSegments.Text);
int extrSegmentDuration = int.Parse(_txtExtraDurationAllowed.Text);
PortionInfo currentPortion = new PortionInfo();
finalSegments = new List<PortionInfo>();
if (_txtExtraDurationAllowed.Text == "0" || _txtTimeSegments.Text == "0")
{
return;//Check that still needs to be handled
}
else
{
for (int i=0;i< orderedVideoPortions.Count;i++)
{
if (orderedVideoPortions[i].Active)
{
if (orderedVideoPortions[i].PortionLength <= (segmentSize + extrSegmentDuration))
{
finalSegments.Add(orderedVideoPortions[i]);
currentPortion = orderedVideoPortions[i];
currentPortion.Active = false;
orderedVideoPortions[i]=currentPortion ;
}
else
{
currentPortion = orderedVideoPortions[i];
finalSegments.Add(new PortionInfo(currentPortion.Start, currentPortion.Start+ segmentSize, currentPortion.VideoIndex, currentPortion.PortionIndex));
currentPortion.Start += segmentSize;
currentPortion.PortionLength = currentPortion.End - currentPortion.Start;
orderedVideoPortions[i] = currentPortion;
orderedVideoPortions.Sort(SortAscending);
i = 0;//Note: Needs to be rechecked because --i should be enough.
}
}
}
Application.DoEvents();
_lblStatus.Text = "Video segments generated. Now Working on generating final video";
}
}

How do i filter and remove lines that don't contain the specifc word/s?

This is the method for now:
private void WordsFilter(List<string> newText)
{
for (int i = 0; i < newText.Count; i++)
{
for (int x = 0; x < WordsList.words.Length; x++)
{
lineToPost = ScrollLabel._lines[i];
if (!lineToPost.Contains(WordsList.words[x]))
{
newText.Remove(lineToPost);
}
}
}
}
newText is List and WorldsList.words is string[]
I loop over the lines in newText and loop over the words and i want to check this way:
First line in newText to loop over all the words if none of any of the words exist in this line remove the current line and the next line after it.
For example in newText if line in index 0 is : Hello everyone
And line in index 1 is: created at 12/3/2002
Then remove index 0 and index 1
Index 2 is empty like a space empty line so do not remove it.
Then index 3 to loop over all the words if nonoe of the words exist in line in index 3 remove index 3 and index 4 .
And so on...
How can i do it ?
Here a working example. I try to didnt change the logic of your code :
using System;
using System.Collections.Generic;
public class Program
{
public static void Main()
{
List<string> list = new List<string>() {"truc", "I love toto", "next", "chocolate", "tata tata", "", "something"};
WordsFilter(list);
}
private static void WordsFilter(List<string> newText)
{
string[] WordsList = new string[] { "toto", "tata" };
for (int i = 0; i < newText.Count; i++)
{
for (int x = 0; x < WordsList.Length; x++)
{
if (newText[i].Contains(WordsList[x]))
{
newText.RemoveAt(i);
if (i + 1 < newText.Count)
newText.RemoveAt(i);
}
}
}
// print
foreach(var item in newText)
{
Console.WriteLine(item);
}
}
}
You should check how works foreach loop and LINQ.

Categories

Resources