C# List & Sort URLs by FileName - c#

I want to make this:
anywhere.com/file/mybirthday.avi
anywhere.com/file/yourbirthday.avi
somewhere.com/file/mybirthday.avi
somewhere.com/file/yourbirthday.avi
To This:
anywhere.com/file/mybirthday.avi
somewhere.com/file/mybirthday.avi
##############
anywhere.com/file/yourbirthday.avi
somewhere.com/file/yourbirthday.avi
I found filenames with regex. And I sorted them. So my codes are here:
private void button1_Click(object sender, EventArgs e)
{
string gelenler = textBox2.Text;
gelenler = gelenler.Replace("\r\n\r\n", "\r\n");
string cikti = string.Empty;
string regex = #"([^\/\\]+\.\w+)$";
string[] parca = Regex.Split(gelenler, "\r\n");
string[] parca2 = new string[parca.Length];
for (int i = 0; i < parca.Length; i++)
{
string ad = match(regex, parca[i]);
parca2[i] = ad;
}
Array.Sort(parca2);
for (int j = 0; j < parca2.Length; j++)
{
for (int i = 0; i < parca2.Length; i++)
{
if (parca2[i].IndexOf(match(regex,parca[j]))!=-1)
{
textBox1.Text += parca[i] + Environment.NewLine;
parca[i] = "";
}
textBox1.Text += "#############" + Environment.NewLine;
}
}
}
private string match(string regex, string html, int i = 1)
{
return new Regex(regex, RegexOptions.Multiline).Match(html).Groups[i].Value.Trim();
}
But didn't working. Any ideas ?
//Sorry my English

I think always the best idea is to use existing .net framework stuff, as in this case Path.GetFileName:
var strings = new[]
{
"anywhere.com/file/mybirthday.avi",
"anywhere.com/file/yourbirthday.avi",
"somewhere.com/file/mybirthday.avi",
"somewhere.com/file/yourbirthday.avi"
};
strings = strings.OrderBy(x => Path.GetFileName(x)).ToArray();
foreach (var s in strings)
{
Console.WriteLine(s);
}
Console.ReadKey();

I think you mean grouping the files; in which case the following code can be used:
IEnumerable<IGrouping<string, string>> groups = strings.GroupBy(x => Path.GetFileName(x)).OrderBy(g => g.Key);
foreach (var group in groups)
{
foreach (var str in group)
{
Console.WriteLine(str);
}
Console.WriteLine("#############");
}

You should use the Uri class. Use the Segements property in order to get the file name (it will be the last segment).
var uris = new[]
{
new Uri("http://anywhere.com/file/mybirthday.avi"),
new Uri("http://anywhere.com/file/yourbirthday.avi"),
new Uri("http://somewhere.com/file/mybirthday.avi"),
new Uri("http://somewhere.com/file/yourbirthday.avi")
};
var filename = uris.OrderBy(x => x.Segments[x.Segments.Length - 1]).ToArray();
foreach (var f in filename)
{
Console.WriteLine(f);
}

Related

Why a method is modifying a List<string> variable in my Load Page?

I want to create two List with methods, the first method create a new list, and the second modify the first one but return a new one. For example, the first list has 200 items, and after add and delete some items in the second method, the returned one has 120 items.
But the second method is actually modifying the first list (now both list has 120 items).
What am I doing wrong?.
PD. I'm learning
protected void Page_Load(object sender, EventArgs e)
{
List<string> firstList = OEEClass.GetCompleteListDocument(DateTime.Today, "BZX"); // Let say it has 200 items
List<string> modifiedList = OEEClass.ModifyList(firstList); // The returned list has less items
}
public class OEEClass
{
public static List<string> GetCompleteListDocument(DateTime Fecha, string noMaquina)
{
var rawDoc = new HtmlDocument();
var tempList = new List<string>();
string url = #"C:/www/WPCS-Feedback/" + Fecha.Year + "/" + Fecha.Month + "/" + Fecha.Day.ToString("d2") + "/" + "Production state data.htm";
if (File.Exists(url) == true)
{
rawDoc.Load(url);
string cleanString = rawDoc.DocumentNode.InnerText.Trim().Replace(" ", "");
cleanString = Regex.Replace(cleanString, #"^\s+$[\r\n]*", string.Empty, RegexOptions.Multiline);
tempList = Regex.Split(cleanString, "\r\n|\r|\n").ToList();
tempList.RemoveRange(0, 5);
for (int j = 0; j < tempList.Count; j++)
{
if (tempList[j].StartsWith("ProductionTerminated") || tempList[j].StartsWith("ProductionInterrumpted"))
{
tempList.Insert(j + 4, "PressSingleCycleActivated=0");
}
}
}
return tempList;
}
public static List<string> ModifyList(List<string> completeListDocument)
{
for (int i = 0; i < completeListDocument.Count; i++)
{
if (completeListDocument[i].StartsWith("MachineSetup"))
{
completeListDocument.RemoveRange(i, 6);
i--;
}
}
return completeListDocument;
}
}
The simplest thing you can do is make a copy of your list before modifying it:
public static List<string> ModifyList(List<string> completeListDocument)
{
var results = new List<string>(completeListDocument);
for (int i = 0; i < results.Count; i++)
{
if (results[i].StartsWith("MachineSetup"))
{
results.RemoveRange(i, 6);
i--;
}
}
return results;
}

How to split path to set of Path

I have one path variable like 'Customer\\Calls\\A1\\A2\\A3\\A4'.From this i want split it into an array like
'Customer'
'Customer\Calls'
'Customer\Calls\A1'
'Customer\Calls\A1\A2'
'Customer\Calls\A1\A2\A3'
'Customer\Calls\A1\A2\A3\A4'
If we do it like
string[] directories = currentFolderPath.Split(Path.DirectorySeparatorChar);
we will get a set of folder,but it will not get in above structure
Can anyone suggest a better approach
Get parent directory until you get to the root
if it's an absolute path
private static IEnumerable<string> SplitPath(string path){
do{
yield return path;
path=Path.GetDirectoryName(path);
} while(path!=null);
}
if it is a relative path
private static IEnumerable<string> SplitRelativePath(string path){
do{
yield return path;
var lastIndex=path.LastIndexOf('\\');
if(lastIndex==-1)
yield break;
path=path.Substring(0, lastIndex);
} while(path!=null);
}
//usage
SplitRelativePath(#"Customer\Calls\A1\A2\A3\A4");
/* result:
C:\Customer\Calls\A1\A2\A3\A4
C:\Customer\Calls\A1\A2\A3
C:\Customer\Calls\A1\A2
C:\Customer\Calls\A1
C:\Customer\Calls
C:\Customer
C:\ *
string path = #"Customer\Calls\A1\A2\A3\A4";
var sections = path.Split('\\').ToList();
var result = Enumerable.Range(0, sections.Count)
.Select(index => string.Join(#"\", sections.Take(index + 1)))
.ToList();
//Result:
// Customer
// Customer\Calls
// Customer\Calls\A1
// Customer\Calls\A1\A2
// Customer\Calls\A1\A2\A3
// Customer\Calls\A1\A2\A3\A4
It's not really obvious from your post, but if you need to do something with each item in your array, I would probably take this approach:
string path = string.Empty;
"Customer\\Calls\\A1\\A2\\A3\\A4".Split(new Char[] { '\\' }).ToList().ForEach(
part => {
path = Path.Combine(path, part);
// Do stuff!
}
);
// easy and simple try this
string path = #"Customer\Calls\A1\A2\A3\A4";
string[] pathArr = path.Split('\\');
List<string> list = new List<string>();
for (int i = 0; i < pathArr.Length; i++)
{
string temp = pathArr[i];
if (i > 0)
{
temp = list[i - 1].ToString() + #"\" + temp;
}
list.Add(temp);
}
string path = "Customer\\Calls\\A1\\A2\\A3\\A4";
var pathArr = path.Split(new string[] { "\\" }, StringSplitOptions.None);
var pathList = new List<string>();
while (pathArr.Length != pathList.Count)
{
string modifiedPath = "";
for (int i = 0; i < pathArr.Length; i++)
{
modifiedPath = modifiedPath + pathArr[i] + "\\";
if (i == pathList.Count)
{
pathList.Add(modifiedPath);
break;
}
}
}
foreach (var str in pathList)
{
Console.WriteLine(str.Remove(str.Length - 1));
}
Console.ReadKey();

Where to add an if statement inside for foreach loop?

I have a CSV file like this:
1,01/01/2001,hello
2,19/09/2013,world
3,12/05/2016,world
4,13/05/2016,hello
5,12/12/2012,world
6,05/02/2006,world
7,06/03/2011,hello
I have this set of code from a question I asked yesterday:
string parts = new StringReader(#"C:\input.txt").ReadToEnd();
string[] lines = parts.Split(new string[] { Environment.NewLine }, StringSplitOptions.None);
StringBuilder sb = new StringBuilder();
List<string> dates = new List<string>();
for (int i = 0; i < lines.Length; i++)
{
string[] data = lines[i].Split(new string[] { "," }, StringSplitOptions.None);
dates.Add(data[1]);
}
var datesSorted = dates.OrderBy(x => DateTime.ParseExact(x, "dd/MM/yyyy", null));
foreach (string s in datesSorted)
{
sb.AppendLine(s + "<br />");
}
Label1.Text = sb.ToString();
The above code works just fine but now I have another problem. I want to add an if statement within the code to only display the chosen value's date and all I could think of is doing either something like this:
string parts = new StringReader(#"C:\input.txt").ReadToEnd();
string[] lines = parts.Split(new string[] { Environment.NewLine }, StringSplitOptions.None);
StringBuilder sb = new StringBuilder();
List<string> dates = new List<string>();
for (int i = 0; i < lines.Length; i++)
{
string[] data = lines[i].Split(new string[] { "," }, StringSplitOptions.None);
dates.Add(data[1]);
var datesSorted = dates.OrderBy(x => DateTime.ParseExact(x, "dd/MM/yyyy", null));
if (data[2] == "hello")
{
foreach (string s in datesSorted)
{
sb.AppendLine(s + "<br />");
}
Label1.Text = sb.ToString();
}
}
Or placing the if statement within the foreach loop, which results in the same output:
01/01/2001
01/01/2001
19/09/2013
12/05/2016
13/05/2016
01/01/2001
05/02/2006
06/03/2011
12/12/2012
19/09/2013
12/05/2016
13/05/2016
It seems to me that you could make your code much simpler with LINQ.
Try this:
var lines = File.ReadAllLines(#"C:\input.txt");
var query =
from line in lines
let data = line.Split(',')
where data[2] == "hello"
orderby DateTime.ParseExact(data[1], "dd/MM/yyyy", null)
select data[1];
var dates = query.ToList();
Label1.Text = String.Join("", dates.Select(x => x + "<br />"));
This handles the if statement you wanted with the where data[2] == "hello" in the query.
One of the things you may want to consider doing instead is to use an intermediate class to represent a csv line, e.g.
private class CSVEntry
{
public int EntryNo { get; set; }
public DateTime Date { get; set; }
public string Text { get; set; }
}
And then change your data loading to:
List<CSVEntry> csvlist = new List<CSVEntry>();
for (int i = 0; i < lines.Length; i++)
{
string[] data = lines[i].Split(new string[] { "," }, StringSplitOptions.None);
csvlist.Add(new CSVEntry() { EntryNo = Int32.Parse(data[0]), Date = DateTime.ParseExact(data[1], "dd/MM/yyyy", null), Text = data[2] });
}
Then chose what to display by doing something like:
var results = csvlist.Where(x => x.Text == "hello").OrderBy(x => x.Date);
Label1.Text = String.Join("<br />", results.Select(x => x.Date.ToString("dd/MM/yyyy"));
The benefit to doing it this way is that you can re use what you have loaded in previously, and any changes to display new values can be done in a LINQ projection.
Edit:
I suggest you move the 'loading' into a separate function, e.g.
public List<CSVEntry> LoadData(string filename, ... other params) {...
and then the part where you want to find specific entries
public IEnumerable<CSVEntry> FindByName(List<CSVEntry> loadedData, ICollection<string> targetNames)
{
return loadedData.Where(x => targetNames.Contains(x.Text));
}
Moving on, you can call it by passing an array/list to the function
var results = FindByName(csvList, new string[] { "hello", "world"});

Error Cannot implicitly convert type 'string[]' to 'string'

I am experiencing an Error within nouns[i] = SearchKeywords(words, sentences); every time I run my program. What should I do?
*I edited to include the SearchKeywords method. I am trying to find all words that have "a" and "an" before them.
Error is,
Error Cannot implicitly convert type 'string[]' to 'string'
string[] SearchKeywords(List<string> keywords, string[] sentence){
int[] location = new int[sentence.Length];
foreach (string word in keywords)
{
for (int i = 0; i < sentence.Length;i++ )
{
string[] nouns = new string[i];
if (String.IsNullOrEmpty(sentence[i]))
{
return null;
}
else
{
location[i] = sentence[i].IndexOf(word);
nouns[i] = sentence[i].Substring(location[i]);
if (nouns[i].Contains(word)) return nouns;
}
}
}
return sentence;
string[] checkForIndefinite()
{
string input = txtEntry.Text;
string text = lbltxtOutput.Text;
Tools tool = new Tools();
List<string> words = new List<string>();
words.Add("an");
words.Add("a");
foreach(string sentence in GetWords(text))
{
for (int i = 0; i < sentence.Length; i++)
{
string[] nouns = new string[i];
string[] sentences = new string[i];
sentences[i] = sentence;
**nouns[i] = SearchKeywords(words, sentences);**
return nouns;
}
}
return null;
}
It seems to me that this is what you need:
string[] SearchKeywords(List<string> keywords, string[] sentence)
{
return
sentence
.Zip(sentence.Skip(1), (w0, w1) => new { w0, w1 })
.Where(ww => keywords.Contains(ww.w0))
.Select(ww => ww.w1)
.ToArray();
}
string[] checkForIndefinite()
{
var input = txtEntry.Text;
var text = lbltxtOutput.Text;
var words = new List<string>() { "an", "a" };
return SearchKeywords(words, GetWords(text));
}
The output of the SearchKeywords function is an string[] and the nouns[i] is a string and simply you cannot assign and string[] value to a string. So You may what to try something like this:
List<string> nouns = new List<string>();
//foreach loop
// for loop
nouns.AddRange(SearchKeywords(words, sentences));
using System;
using System.Security.Cryptography;
using System.Text;
using System.Collections.Generic;
public class Program
{
public static void Main()
{
string[] indefinites = checkForIndefinite();
foreach (string s in indefinites)
{
Console.WriteLine(s);
}
}
static string[] SearchKeywords(List<string> keywords, string sentence)
{
if (String.IsNullOrEmpty(sentence))
{
return null;
}
List<string> nouns = new List<string>();
string[] words = sentence.Split(' ');
foreach (string keyword in keywords)
{
for (int i = 0; i < words.Length; i++ )
{
if (words[i] == keyword)
{
if (i+1 < words.Length && !nouns.Contains(words[i+1]))
{
nouns.Add(words[i+1]);
}
}
}
}
return nouns.ToArray();
}
static string[] checkForIndefinite()
{
string sentence = "This is not an interesting sentence to use to test a program";
string text = string.Empty;
List<string> words = new List<string>();
words.Add("an");
words.Add("a");
return SearchKeywords(words, sentence);
}
}
This compiles and returns the following:
interesting
program

Locating items in List whether they occur more than once in C#

In addition to the question: Get List<> element position in c# using LINQ
First of all, let me explaing why I do what I do :)
I'm trying to encrypt a string into a one-line code which holds how many times a letter is used in the string and also with its positions. By this method, I'll be able to decrypt the code and get(reproduce) the full text again. Let's say myString is "How are you today". I'll encrypt it like
o3[1,9,13]," "3[3,7,11],a2[4,15],y2[9,17],H1[0],w1[2],r1[5],e1[6],u1[10],t1[12],d1[14],?[18]
I know it looks odd but think about working on bigger strings like e-books. This could handle all the text in one or two lines.
The encryption is not about the security, it's just about holding big datas in smaller spaces.
In my code, I can convert the string into list, count how many times a letter is used but I can't define the positions of the letters when they occur more than once.
private void btnKoda_Click(object sender, EventArgs e)
{
var yazi = txtYazi.Text;
List<char> liste = yazi.ToList();
List<string> tut = new List<string>();
foreach (char harf in liste)
{
for (int i = 0; i < liste.Count; i++)
{
char ekle = liste[i];
tut.Add(ekle.ToString());
}
foreach (var karakter in tut)
{
txtKod.Text += karakter;
}
// holds statics
var istatistik =
from c in tut
group c by c into g
select new { g.Key, say = g.Count() };
var enCok =
from giris in istatistik
orderby giris.say descending
select giris;
foreach (var giris in enCok)
{
txtHarfler.Text += string.Format("{0}: {1}\r\n", giris.Key, giris.say);
}
break;
}
Not sure what's going on in your code, but here's how I would do it:
private void button1_Click(object sender, EventArgs e)
{
Dictionary<Char, Encoding> dct = new Dictionary<char, Encoding>();
string data = "How are you today";
for(int i = 0; i < data.Length; i++)
{
Char C = data[i];
if (!dct.ContainsKey(C))
{
dct.Add(C, new Encoding(C));
}
dct[C].AddOccurence(i);
}
StringBuilder SB = new StringBuilder();
foreach(Encoding enc in dct.Values)
{
if (SB.Length == 0)
{
SB.Append(enc.ToString());
}
else
{
SB.Append("," + enc.ToString());
}
}
Console.WriteLine(SB.ToString());
}
Here's the Encoding class:
public class Encoding
{
private Char _C;
private List<int> _Positions;
private Encoding() {}
public Encoding(Char C)
{
this._C = C;
this._Positions = new List<int>();
}
public Char Character
{
get
{
return _C;
}
}
public int Count
{
get
{
return _Positions.Count;
}
}
public int[] Occurences
{
get
{
return _Positions.ToArray();
}
}
public override string ToString()
{
string[] values = Array.ConvertAll(this.Occurences.ToArray(), x => x.ToString());
return this.Character.ToString() + this.Count.ToString() + "[" + String.Join(",", values) + "]";
}
public void AddOccurence(int position)
{
this._Positions.Add(position);
}
}
Original String:
How are you today
Output:
H1[0],o3[1,9,13],w1[2], 3[3,7,11],a2[4,15],r1[5],e1[6],y2[8,16],u1[10],t1[12],d1[14]

Categories