Read a file to List<int> [closed] - c#

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 5 years ago.
Improve this question
I am needing to create a list of numbers from an uploaded file, if the numbers have "-" representing a range, I need to split the numbers, making the first number a start, iterate through til it gets to the second number. I know I will be storing the numbers in a List, I'm just not sure on how to break out the numbers in the file with "-", Here is an example of the file:
099985-10043
102609-102886
102917-102921
106100-106101
110684-110685
114886-114887
117765-117766
120604-120605
121157-121158
121627-121911
122539
and here is where I am with the code:
if(string.IsNullOrEmpty(fileName.Text)) return;
_MissingInt = new List<int>();
var lines = File.ReadAllLines(fileName.Text);
foreach (string line in lines) {
...need help with logic...
}
I would greatly appreciate any direction and help as my programming skills are pretty weak and I am learning...this is not homework

I will assume that the file contains lines which can have two int values maximum, separated by -. Let's suppose we have a class like this:
class Interval {
public int left;
public int right;
public bool hasRight;
public Interval(int left, int right) {
this.left = left;
this.right = right;
hasRight = true;
}
public Interval(int left) {
this.left = left;
hasRight = false;
}
}
Now let's implement a parser method:
protected Interval parse(String line) {
String[] parts = line.Split(new string[] {"-"});
int left, right;
if (!Int32.TryParse(parts[0], left)) {
return null; //Invalid interval
}
return ((parts.length <= 1) || (!Int32.TryParse(parts[1], right))) ? (new Interval(left)) : (new Interval(left, right));
}
And another:
protected Interval[] aggregateParse(String[] lines) {
Interval[] intervals = new Interval[lines.Length];
for (int i = 0; i < lines.Length; i++) {
intervals[i] = parse(lines[i]);
}
return intervals;
}
This could be used to generate intervals. If we need to get the integers between the edges of the interval and store them, then we can use a for cycle, starting from the left edge and ending at the right edge, filling an array of right - left - 1 size, which might be a member of interval. The problem is that an interval which is opened to the right will never end, so make sure you do this wisely.

Linq-style solution that supports all wrong input like strings and empty lines. For example:
1
sfd
2
5-10
11-fdfd
12 13
14
int x;
var res = lines
// filter out empty lines
.Where(line => !string.IsNullOrEmpty(line))
// convert ranges to pairs
.Select(line => line.Split('-'))
// filter out not numbers
.Where(line => line.All(number => int.TryParse(number, out x)))
// convert all strings to int
.Select(item => item.Select(int.Parse).ToList())
.SelectMany(item =>
{
if (item.Count > 1)
{
return Enumerable.Range(item[0], item[1] - item[0] + 1);
}
return item;
})
.ToList();

I didn't agree with Badiparmagi's answer as its adding string/character to int list, its not compilable code.
Here giving you my tested attempt. I hope it may help you.
if (string.IsNullOrEmpty(fileName.Text)) return;
var _MissingInt = new List<int>();
var lines = File.ReadAllLines(fileName.Text);
foreach (var line in lines)
{
if(string.IsNullOrEmpty(line))
continue;
if (line.Contains("-"))
{
var range = line.Split('-');
int startNumber;
int endNumber;
if(int.TryParse(range[0], out startNumber) && int.TryParse(range[1]), out endNumber)
for (var i = startNumber; i < endNumber; i++)
{
_MissingInt.Add(i);
}
}
else
{
int num;
if(int.TryParse(line, out num))
_MissingInt.Add(num);
}
}

Related

C# - optimize logic [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 5 years ago.
Improve this question
I have a list of object. Those objects contain lat and lon coordinates among other properties. I want to extract only thoose coordonates that satisfy
(Math.Abs(elem1.lat - elem2.lat) > Delta && Math.Abs(elem1.lon - elem2.lon) > Delta)
Basically I want to extract only objects that dont have coordinates close to each other.
Is there an elegant way to do this with C# LINQ ?
EDIT 1 :
So elem1 and elem2 are any 2 elements from the list. I elements that will result from the query to have more then delta between any 2 of them
EDIT 2 :
This is my code at the moment. It works as I want :
for (int i = 0; i < companyHistory.Count; i++)
{
var isOk = true;
var count = zoomApprovedHistory.Count;
for (var j = 0; j < count; j++)
{
if (Math.Abs(companyHistory[i].X - zoomApprovedHistory[j].X) < delta && Math.Abs(companyHistory[i].Y - zoomApprovedHistory[j].Y) < delta)
{
isOk = false;
break;
}
}
// if no other point is close add it to approved array for this zoom
if (isOk)
{
zoomApprovedHistory.Add(companyHistory[i]);
}
}
How can I optimize it ? it has O(n^2) complexity. Looking for the fastest option
Your question is not well-phrased. If your elem1 or elem2 is a single item you want to compare against, this is pretty easy. Just do a LINQ Where to find the items that match the criteria.
Coordinates it = new Coordinates { lat = 5, lon = 5 };
var picked = list.Where(x => Math.Abs(x.lat - it.lat) < Delta && Math.Abs(x.lon - it.lon) < Delta);
If, on the other hand, your two elements are any two elements in the list, then you run into a problem where you need to clarify things. As I mentioned in my comment, if your have elem1, elem2, and elem3, and if the first two don't match the criteria but if elem2 and elem3 do match the criteria, then are both of those elements (2 and 3) 'hits'? Assuming they are, the solution below will work. I wrote a simple Comparer to help make things easy as well.
public class CoordinateComparer : IEqualityComparer<Coordinates>
{
public bool Equals(Coordinates x, Coordinates y)
{
return (x.lat == y.lat && x.lon == y.lon);
}
public int GetHashCode(Coordinates obj)
{
unchecked
{
int hash = 17;
if (obj != null)
{
hash = hash * 23 + obj.lat.GetHashCode();
hash = hash * 23 + obj.lon.GetHashCode();
}
return hash;
}
}
}
public class Coordinates
{
public int lat { get; set; }
public int lon { get; set; }
}
class MainClass
{
public static void Main(string[] args)
{
List<Coordinates> list = new List<Coordinates>();
list.Add(new Coordinates { lat = 5, lon = 4 });
list.Add(new Coordinates { lat = 4, lon = 5 });
list.Add(new Coordinates { lat = 7, lon = 4 });
list.Add(new Coordinates { lat = 6, lon = 3 });
list.Add(new Coordinates { lat = 8, lon = 2 });
double Delta = 1.1;
List<Coordinates> results = new List<Coordinates>();
foreach(Coordinates item in list)
{
// Find items that match the condition
var matches = list.Where(x => Math.Abs(x.lat - item.lat) < Delta && Math.Abs(x.lon - item.lon) < Delta);
// The 'item' will always match the condition with itself, which is undesirable, so remove it
matches = matches.Except(new List<Coordinates> { item }, new CoordinateComparer());
// Add the items that are not already in it to the results list
results.AddRange(matches.Where(x => !results.Contains(x, new CoordinateComparer())));
}
foreach (Coordinates item in results)
Console.WriteLine("Lat : {0}, Lon : {1}", item.lat, item.lon);
Console.ReadLine();
}
}
Bear in mind that if your latitude and longitude coordinates are either double or float, which they probably are, you might run into problems when comparing. But that's an altogether different question.

Algorithm for shortest list of words

The issue is as follows: the user provides a StartWord and EndWord string of X letters together with a list of strings that are also of length X (lets make it 4 but probably more)
static void Main(string[] args)
{
string StartWord = "Spot";
string EndWord = "Spin";
List<string> providedList = new List<string>
{
"Spin", "Spit", "Spat", "Spot", "Span"
};
List<string> result = MyFunc(StartWord, EndWord, providedList);
}
public List<string> MyFunc(string startWord, string endWord, List<string> input)
{
???
}
From the provided parameters I need to display to the user a result that comprises of the SHORTEST list of 4 letter words, starting with StartWord and ending with EndWord with a number of intermediate words that are to be found in the list, where each word differs from the previous word by PRECISELY one letter.
For example the above code should return a list of strings containing these elements:
Spot(as FirstWord),
Spit(only one letter is different from previous word),
Spin (as EndWord)
A bad exapmle would be: Spot, Spat, Span, Spin (as it takes 3 changes compared to the above 2)
I have been looking at some matching algorithms and recursion, but I am not able to figure out how to go about this.
Thank you for any kind of help in advance.
Create a graph where the vertices are words, and an edge connects any two words that differ by one letter.
Do a breadth-first search, starting at the StartWord, looking for the shortest path to the EndWord.
Here is sample code for this solution in a different language (Python). That may give you an even better pointer. :-)
def shortestWordPath (startWord, endWord, words):
graph = {}
for word in words:
graph[word] = {"connected": []}
for word in words:
for otherWord in words:
if 1 == wordDistance(word, otherWord):
graph[word]['connected'].append(otherWord)
todo = [(startWord,0)]
while len(todo):
(thisWord, fromWord) = todo.pop(0)
if thisWord == endWord:
answer = [thisWord, fromWord]
while graph[ answer[-1] ]["from"] != 0:
answer.append(graph[ answer[-1] ]["from"])
answer.reverse()
return answer
elif "from" in graph[thisWord]:
pass # We have already processed this.
else:
graph[thisWord]["from"] = fromWord
for nextWord in graph[thisWord]["connected"]:
todo.append([nextWord, thisWord])
return None
def wordDistance (word1, word2):
return len(differentPositions(word1, word2))
def differentPositions(word1, word2):
answer = []
for i in range(0, min(len(word1), len(word2))):
if word1[i] != word2[i]:
answer.append(i)
for i in range(min(len(word1), len(word2)),
max(len(word1), len(word2))):
answer.append(i)
return answer
print shortestWordPath("Spot", "Spin",
["Spin", "Spit", "Spat", "Spot", "Span"])
This is what I ended up using(please feel free to comment on the up and down side of it):
private List<List<string>> allWordSteps;
private string[] allWords;
public List<string> WordLadder(string wordStart, string wordEnd, string[] allWordsInput)
{
var wordLadder = new List<string>() { wordStart };
this.allWordSteps = new List<List<string>>() { wordLadder };
allWords = allWordsInput;
do
{
wordLadder = this.IterateWordSteps(wordEnd);
}
while (wordLadder.Count() == 0);
return wordLadder;
}
private List<string> IterateWordSteps(string wordEnd)
{
List<List<string>> allWordStepsCopy = this.allWordSteps.ToList();
this.allWordSteps.Clear();
foreach (var wordSteps in allWordStepsCopy)
{
var adjacent = this.allWords.Where(
x => this.IsOneLetterDifferent(x, wordSteps.Last()) &&
!wordSteps.Contains(x));
if (adjacent.Contains(wordEnd))
{
wordSteps.Add(wordEnd);
return wordSteps;
}
foreach (var word in adjacent)
{
List<string> newWordStep = wordSteps.ToList();
newWordStep.Add(word);
this.allWordSteps.Add(newWordStep);
}
}
return new List<string>();
}
private bool IsOneLetterDifferent(string first, string second)
{
int differences = 0;
if (first.Length == second.Length)
{
for (int i = 0; i < first.Length; i++)
{
if (first[i] != second[i])
{
differences++;
}
}
}
return differences == 1;
}

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 to sort a List<Process> by Window Title [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 8 years ago.
Improve this question
I am sure I would do this, but the way I am thinking how to achieve this makes me sad, so I am asking for better way
List<Process> myList = new List<Process>();
Process[] processlist = Process.GetProcesses(); // Load all existing processes
// Pin existing sessions to the application
foreach (Process p in processlist)
{
if (p.MainWindowTitle.Contains("TX")) // schema is like TX1 => TX10, but this loop is not sorted at all
{
myList.Add(p); // Unsorted list when looking by MainWindowTitle property
}
}
Sorry fot nor precising the question about what kind of sorting I want to achieve
[0] TX1
[1] TX2
...
[5] TX6
etc.
You could try something like this:
var myList = processlist.Where(p=>p.MainWindowTitle.Contains("TX"))
.OrderBy(p=>p.MainWindowTitle)
.ToList();
How about using LINQ's OrderBy and a simple custom comparer. In this case this might be enough. From the information you gave us it should work for you.
class Program
{
static void Main(string[] args)
{
var names = new string[] { "TX2", "TX12", "TX10", "TX3", "TX0" };
var result = names.OrderBy(x => x, new WindowNameComparer()).ToList();
// = TX0, TX2, TX3, TX10, TX13
}
}
public class WindowNameComparer : IComparer<string>
{
public int Compare(string x, string y)
{
string pattern = #"TX(\d+)";
var xNo = int.Parse(Regex.Match(x, pattern).Groups[1].Value);
var yNo = int.Parse(Regex.Match(y, pattern).Groups[1].Value);
return xNo - yNo;
}
}
The WindowNameComparer reads (parses) the numbers attached to the TX and calculates the difference which is then used for sorting according to this table for the IComparer.Compare Method
Value Meaning
Less than zero x is less than y.
Zero x equals y.
Greater than zero x is greater than y.
Well, I made this almost without linq, but I guess it's overkill
Process temp = null;
for (int i = 0; i < Games.Count; i++)
{
for (int sort = 0; sort < Games.Count - 1; sort++)
{
string title1 = Games[sort].MainWindowTitle;
string title2 = Games[sort+1].MainWindowTitle;
int titleAsIntSum1 = title1.Sum(b => b); // This will work in this case
int titleAsIntSum2 = title2.Sum(b => b);
if (titleAsIntSum1 > titleAsIntSum2)
{
temp = Games[sort + 1];
Games[sort + 1] = Games[sort];
Games[sort] = temp;
}
}
}

More efficient looping? [closed]

Closed. This question is off-topic. It is not currently accepting answers.
Want to improve this question? Update the question so it's on-topic for Stack Overflow.
Closed 9 years ago.
Improve this question
So I'm writing a simple struct to act like an Array of strings but with some handy operators and other functions that I've always wanted to see in strings. Specifically the method I'm working on right now is the / operator. The problem is, it won't add on any remainders at the end like I want it to.
What it's supposed to do, is take an array of strings, like {"Hello", "Test1", "Test2", "Goodbye", "More?", "Qwerty"} and, say I want to divide by 4, it should return { {"Hello", "Test1", "Test2", "Goodbye"}, {"More?", "Qwerty"} } but it doesn't.
The whole class (the method I want to improve is the / operator, but if you see anything else I can work on please point it out) (I know barely any of it is commented. Sorry about that, didn't expect anyone else to see this code aside from me.):
public struct StringCollection
{
private String[] value;
public StringCollection(params String[] s)
{
this.value = s;
}
public StringCollection(StringCollection current, String ad)
{
if (current.value == null) {
current.value = new String[0] { };
}
this.value = new String[current.value.Length+1];
for (int i=0; i<this.value.Length; i++)
{
try {
this.value[i] = current[i];
} catch {
break;
}
}
this.value[this.value.Length-1] = ad;
}
public StringCollection(StringCollection x, params StringCollection[] y)
{
this.value = x.value;
for (int j=0;j<y.Length;j++)
{
for (int i=0;i<y[j].value.Length;i++)
{
this += y[j][i];
}
}
}
public static StringCollection[] operator /(StringCollection x, int y)
{
StringCollection[] result = null;
if (((int)x.value.Length/y) == ((double)x.value.Length)/y)
result = new StringCollection[y];
else
result = new StringCollection[y+1];
for (int j=0;j<y;j++)
{
for (int i=0;i<((int)x.value.Length/y);i++)
{
result[j] += x.value[i+(int)((x.value.Length/y)*j)];
}
}
if (((int)x.value.Length/y) != ((double)x.value.Length)/y)
{
// This is the part that isn't working.
for (int i=0;i<(((int)x.value.Length/y)*result[0].value.Length)-x.value.Length;i++)
{
result[result.Length-1] += x.value[i+((result[0].value.Length)*result.Length-2)];
}
}
return result;
}
public String this[int index]
{
get {
return this.value[index];
}
set {
this.value[index] = value;
}
}
}
What it does is basically takes your array (single array) and splits it into a bunch of arrays that are the same size, then it adds on the remainder in a new array at the end.
Firstly your question isn't really related to loops at all, or at least loops are only addressed in your code. You should have titled this differently.
Secondly your array adding/removing could be improved; i.e. adding 1 to array size every time and removing 1 then re-copying the entire array every time is a time-sink.
Now onto your question, your code should basically look like this:
//Make your return array
int retLen = x.Length / y;
//Add space for the remainder
if(x.Length % y != 0)
retLen++;
var ret = new StringCollection[retLen];
//Reusing variables is a good way to save memory, but watch naming conventions as this can be confusing
retLen = 0;
var tempCollection = new StringCollection();
for (int i = 0; i < x.Length; i++)
{
tempCollection = new StringCollection(tempCollection, x[i]);
if(i % y == 0 || i == x.Length - 1)
{
ret[retLen++] = tempCollection;
tempCollection = new StringCollection();
retLen = 0;
}
}
return ret;
I really don't like that you don't have a Add function in this struct, just so we're clear. the tempCollection = new StringCollection(tempCollection, x[i]); is f$*kin' TERRIBLE when it comes to time CPU time to create all those new objects.
Pretty sure you'll need to tweak that to make sure all items are entered properly, but that was a first attempt, so ... meh o.O Figured since no one was actually going to answer you I'd take the time.
EDIT: Found a bug, forgot to set retLen back to 0 when adding to ret

Categories

Resources