C# Comparing an Input to a String Exactly - c#

I have a list of most of the elements in the periodic table in order of their placement on the table:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Chemistry_Element_Calculator
{
class Program
{
static void Main(string[] args)
{
// Declare all numbers
int electronNumber;
int protonNumber;
float neutronNumber;
int i;
// Declare all strings
string elementRequest;
// Create an list for all elements
List<string> elementNameList = new List<string>();
List<string> elementSymbolList = new List<string>();
// Add all elements to the list
elementNameList.Add("Hydrogen"); elementSymbolList.Add("H");
elementNameList.Add("Helium"); elementSymbolList.Add("He");
elementNameList.Add("Lithium"); elementSymbolList.Add("Li");
elementNameList.Add("Beryllium"); elementSymbolList.Add("Be");
elementNameList.Add("Boron"); elementSymbolList.Add("B");
elementNameList.Add("Carbon"); elementSymbolList.Add("C");
elementNameList.Add("Nitrogen"); elementSymbolList.Add("N");
elementNameList.Add("Oxygen"); elementSymbolList.Add("O");
elementNameList.Add("Fluorine"); elementSymbolList.Add("F");
elementNameList.Add("Neon"); elementSymbolList.Add("Ne");
elementNameList.Add("Sodium"); elementSymbolList.Add("Na");
elementNameList.Add("Magnesium"); elementSymbolList.Add("Mg");
elementNameList.Add("Aluminium"); elementSymbolList.Add("Al");
elementNameList.Add("Silicon"); elementSymbolList.Add("Si");
elementNameList.Add("Phosphorus"); elementSymbolList.Add("P");
elementNameList.Add("Sulfur"); elementSymbolList.Add("S");
elementNameList.Add("Chlorine"); elementSymbolList.Add("Cl");
elementNameList.Add("Argon"); elementSymbolList.Add("Ar");
elementNameList.Add("Potassium"); elementSymbolList.Add("K");
elementNameList.Add("Calcium"); elementSymbolList.Add("Ca");
elementNameList.Add("Scandium"); elementSymbolList.Add("Sc");
elementNameList.Add("Titanium"); elementSymbolList.Add("Ti");
elementNameList.Add("Vanadium"); elementSymbolList.Add("V");
elementNameList.Add("Chromium"); elementSymbolList.Add("Cr");
elementNameList.Add("Manganese"); elementSymbolList.Add("Mn");
elementNameList.Add("Iron"); elementSymbolList.Add("Fe");
elementNameList.Add("Cobalt"); elementSymbolList.Add("Co");
elementNameList.Add("Nickel"); elementSymbolList.Add("Ni");
elementNameList.Add("Copper"); elementSymbolList.Add("Cu");
elementNameList.Add("Zinc"); elementSymbolList.Add("Zn");
elementNameList.Add("Gallium"); elementSymbolList.Add("Ga");
elementNameList.Add("Germanium"); elementSymbolList.Add("Ge");
elementNameList.Add("Arsenic"); elementSymbolList.Add("As");
elementNameList.Add("Selenium"); elementSymbolList.Add("Se");
elementNameList.Add("Bromine"); elementSymbolList.Add("Br");
elementNameList.Add("Krypton"); elementSymbolList.Add("Kr");
elementNameList.Add("Rubidium"); elementSymbolList.Add("Rb");
elementNameList.Add("Strontium"); elementSymbolList.Add("Sr");
elementNameList.Add("Yttrium"); elementSymbolList.Add("Y");
elementNameList.Add("Zirconium"); elementSymbolList.Add("Zr");
elementNameList.Add("Niobium"); elementSymbolList.Add("Nb");
elementNameList.Add("Molybdenum"); elementSymbolList.Add("Mo");
elementNameList.Add("Technetium"); elementSymbolList.Add("Tc");
elementNameList.Add("Rubidium"); elementSymbolList.Add("Ru");
elementNameList.Add("Rhodium"); elementSymbolList.Add("Rh");
elementNameList.Add("Palladium"); elementSymbolList.Add("Pd");
elementNameList.Add("Silver"); elementSymbolList.Add("Ag");
elementNameList.Add("Cadmium"); elementSymbolList.Add("Cd");
elementNameList.Add("Indium"); elementSymbolList.Add("In");
elementNameList.Add("Tin"); elementSymbolList.Add("Sn");
elementNameList.Add("Antimony"); elementSymbolList.Add("Sb");
elementNameList.Add("Tellurium"); elementSymbolList.Add("Te");
elementNameList.Add("Iodine"); elementSymbolList.Add("I");
elementNameList.Add("Xenon"); elementSymbolList.Add("Xe");
elementNameList.Add("Caesium"); elementSymbolList.Add("Cs");
elementNameList.Add("Barium"); elementSymbolList.Add("Ba");
elementNameList.Add("Lanthanum"); elementSymbolList.Add("La");
elementNameList.Add("Cerium"); elementSymbolList.Add("Ce");
elementNameList.Add("Praseodynium"); elementSymbolList.Add("Pr");
elementNameList.Add("Neodymium"); elementSymbolList.Add("Nd");
elementNameList.Add("Promethium"); elementSymbolList.Add("Pm");
elementNameList.Add("Samarium"); elementSymbolList.Add("Sm");
elementNameList.Add("Europium"); elementSymbolList.Add("Eu");
elementNameList.Add("Gadolinium"); elementSymbolList.Add("Gd");
elementNameList.Add("Terbium"); elementSymbolList.Add("Tb");
elementNameList.Add("Dysprosium"); elementSymbolList.Add("Dy");
elementNameList.Add("Holomium"); elementSymbolList.Add("Ho");
elementNameList.Add("Erbium"); elementSymbolList.Add("Er");
elementNameList.Add("Thulium"); elementSymbolList.Add("Tm");
elementNameList.Add("Ytterbium"); elementSymbolList.Add("Yb");
elementNameList.Add("Lutenium"); elementSymbolList.Add("Lu");
elementNameList.Add("Hafnium"); elementSymbolList.Add("Hf");
elementNameList.Add("Tantalum"); elementSymbolList.Add("Ta");
elementNameList.Add("Tungsten"); elementSymbolList.Add("W");
elementNameList.Add("Rhenium"); elementSymbolList.Add("Re");
elementNameList.Add("Osmium"); elementSymbolList.Add("Os");
elementNameList.Add("Iridium"); elementSymbolList.Add("Ir");
elementNameList.Add("Platinum"); elementSymbolList.Add("Pt");
elementNameList.Add("Gold"); elementSymbolList.Add("Au");
elementNameList.Add("Mercury"); elementSymbolList.Add("Hg");
elementNameList.Add("Thallium"); elementSymbolList.Add("Tl");
elementNameList.Add("Lead"); elementSymbolList.Add("Pb");
elementNameList.Add("Bismuth"); elementSymbolList.Add("Bi");
elementNameList.Add("Polonium"); elementSymbolList.Add("Po");
elementNameList.Add("Astatine"); elementSymbolList.Add("At");
elementNameList.Add("Radon"); elementSymbolList.Add("Rn");
elementNameList.Add("Francium"); elementSymbolList.Add("Fr");
elementNameList.Add("Radium"); elementSymbolList.Add("Ra");
elementNameList.Add("Actinium"); elementSymbolList.Add("Ac");
elementNameList.Add("Thorium"); elementSymbolList.Add("Th");
elementNameList.Add("Palladium"); elementSymbolList.Add("Pa");
elementNameList.Add("Uranium"); elementSymbolList.Add("U");
elementNameList.Add("Nepturium"); elementSymbolList.Add("Np");
elementNameList.Add("Plutonium"); elementSymbolList.Add("Pu");
elementNameList.Add("Americium"); elementSymbolList.Add("Am");
elementNameList.Add("Curium"); elementSymbolList.Add("Cm");
elementNameList.Add("Berkelium"); elementSymbolList.Add("Bk");
elementNameList.Add("Californium"); elementSymbolList.Add("Cf");
elementNameList.Add("Einsteinium"); elementSymbolList.Add("Es");
elementNameList.Add("Fermium"); elementSymbolList.Add("Fermium");
elementNameList.Add("Mendelevium"); elementSymbolList.Add("Md");
elementNameList.Add("Nobelium"); elementSymbolList.Add("No");
elementNameList.Add("Lawrencium"); elementSymbolList.Add("Lr");
elementNameList.Add("Rutherfordium"); elementSymbolList.Add("Rf");
elementNameList.Add("Dubnium"); elementSymbolList.Add("Db");
elementNameList.Add("Seaborgium"); elementSymbolList.Add("Sg");
elementNameList.Add("Bohrium"); elementSymbolList.Add("Bh");
elementNameList.Add("Hassium"); elementSymbolList.Add("Hs");
elementNameList.Add("Meitnerium"); elementSymbolList.Add("Mt");
elementNameList.Add("Darmstadtium"); elementSymbolList.Add("Ds");
elementNameList.Add("Roentgenium"); elementSymbolList.Add("Rg");
elementNameList.Add("Copernicium"); elementSymbolList.Add("Cn");
Console.WriteLine("What element do you want? Either input it's full name, with a capital letter, or it's elemnent symbol. E.g. N for Nitrogen");
elementRequest = Console.ReadLine();
elementNameList.ForEach(delegate (String elementName)
{
if (elementRequest == elementName)
{
Console.WriteLine("Hydrogen");
}
else
{
Console.WriteLine("Not Hydrogen");
};
});
Console.Read();
However, when I run the program, and input Hydrogen, both Helium and Hydrogen are said to be hydrogen. How can I fix this?
Also, if anyone has an idea on how to compress the 2 lists so they're smaller, let me know :)
Thanks :)

What you want your code to do is take the index from the first list, and return the string at the same index in the second list.
Your code is currently not doing any of that, but always printing "Hydrogen", your output thus always being "Hydrogen" whatever element is requested.
You can trivially fix that by actually looking up the index:
int indexOfElementName = elementNameList.IndexOf(elementRequest);
string elementSymbol = elementSymbolList[indexOfElementName];
Note that that does not handle casing and requested elements that aren't in the list (or typos).
But keeping the two lists in sync, and this code in general, is a maintenance disaster waiting to happen.
Instead you could use a dictionary where the element name is the key and the symbol the value:
var elementDictionary = new Dictionary<string, string>
{
{ "Hydrogen", "H" },
{ "Helium", "He" },
// ...
}
Then look it up:
string elementSymbol = elementDictionary[elementRequest];
Do note that this still doesn't handle case-insensitivity and elements that are not found, but I'll leave that as an exercise to you.

I would use a custom class and a list as suggested by ElectricRouge.
I don't favor the dictionary because you need to search both by name and symbol. Also, the data set is small (118 elements to date).
See comments for the explanation of the code.
using System;
using System.Collections.Generic;
namespace Chemistry_Element_Calculator
{
// Create a chemical element class
// You can add more properties such as number of electrons, etc.
public class ChemicalElement
{
public string Symbol
{
get; set;
}
public string Name
{
get; set;
}
}
class Program
{
static void Main(string[] args)
{
// Create a list of the elements, populate their properties
var elements = new List<ChemicalElement>()
{
new ChemicalElement {Name = "Hydrogen", Symbol = "H"},
new ChemicalElement {Name = "Helium", Symbol = "He"},
new ChemicalElement {Name = "Lithium", Symbol = "Li"}
// etc.
};
Console.WriteLine("What element do you want? Either input it's full name, with a capital letter, or it's elemnent symbol. E.g. N for Nitrogen");
var elementRequest = Console.ReadLine();
// Use find to get a matching element, compare both name and symbol
var foundElement = elements.Find(element => element.Symbol == elementRequest || element.Name == elementRequest);
if (foundElement == null)
{
// Output if no element is found
Console.WriteLine("Element Not Found");
}
else
{
// Output if the element is found
Console.WriteLine("Found element {0}.", foundElement.Name);
}
Console.WriteLine("[Press any key to finish]");
Console.ReadKey();
}
}
}
The code uses the method List.Find to get the result, it will only return the first match.
I would also suggest to migrate to String.Compare if you want to have case-insensitive comparison.
And finally I would be reading the data form file or a database, but that is beyond the question.

Related

C# iterate List for specific values then Add them to another List in a certain order

Each instance of some Lists in my program are in an arbitrarily different order (as a result of an unfixed bug in Umbraco CMS Forms), and I need to rearrange them to the correct order. I can't use indices and OrderBy as each time the order is different.
I have been trying to iterate the existing List, then, when it finds the correct String that should be in position [0], using .Add to add it to another, empty List. Then continue through adding each value to the correct index.
I can't figure out a way to do this. I need the logic to basically say "look in this list, if the string equals this value, add it to this other list at position 0, then look for the next string to add at position 1, and so on", so at the end I will have the new List in the correct order.
// List to populate from record in wrong order
var extractedFields = new List<KeyValuePair<string, string>>();
// new list to copy values across in correct order
var newOrderFields = new List<KeyValuePair<string, string>>();
// separate list containing data field captions, used to iterate later
var extractedCaptions = new List<string>();
foreach (var field in record.RecordFields)
{
var extractValue = field.Value.ValuesAsString().NullSafeToString();
var extractType = CGHelper.CleanString(field.Value.Field.FieldType.Name).ToLower();
var extractCaption = field.Value.Field.Caption;
extractedFields.Add(new KeyValuePair<string, string>(extractType,
extractValue));
extractedCaptions.Add(extractCaption);
}
var count = 0;
foreach (var cap in extractedCaptions.ToList())
{
if (cap == "Opportunity ID")
{
extractedCaptions.Remove(cap);
extractedCaptions.Insert(0, cap);
var key = extractedFields[count].Key;
var value = extractedFields[count].Value;
newOrderFields.Add(new KeyValuePair<string, string>(key, value));
}
else if (cap == "Name")
{
// etc. identify string to be put into correct order
So to try and explain further, a user submits a form with the fields in a certain order. When we load that form and pull the record through (from the Umbraco Form), it is in a totally different and arbitrary order (and is in a different order for every single form).Therefore I need to iterate the fields and put them back into the order they were in the original form...
I don't know if I understand the situation correctly. But you can utilize the IComparer<T> interface for custom sorting logic.
using System;
using System.Collections.Generic;
namespace Comparer
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Hello World!");
var list = new[]{"Foobar", "Baz", "Foo", "Foobar", "Bar", };
Array.Sort(list, new CustomComparer(new[]{"Foo", "Bar", "Baz", "Foobar"}));
list.Dump();
// will dump : Foo,Bar,Baz,Foobar,Foobar
}
}
public class CustomComparer : IComparer<string>
{
private readonly string[] priorityList;
public CustomComparer(string[] priorityList)
{
this.priorityList = priorityList;
}
public int Compare(string x, string y)
{
var xIx = Array.IndexOf(priorityList, x);
var yIx = Array.IndexOf(priorityList, y);
return xIx.CompareTo(yIx);
}
}
}
This will sort the array according to indexes proved in the constructor.
Fiddle
I wrote a small example.
You can see it working here.
The idea is iterating the ordered list and search to every value in other one.
Code:
using System;
using System.Collections.Generic;
using System.Linq;
public class Program
{
public static void Main()
{
List<string> ordered = new List<string>(){ "a", "b", "c", "d"};
List<string> nonOrderedAndMissing = new List<string>(){ "c", "d", "a"};
// here is the join
var newList = ordered.Select(a => nonOrderedAndMissing.Contains(a) ? a : null).Where(d => d != null).ToList();
// checking here
foreach(var a in newList){
Console.WriteLine(a);
}
}
}

How to collect a list of specific substrings following on a different substring trigger?

I have a large text dataset (~2 GB) of engineering information that was written in Cobol. I am attempting to extract certain substrings within it and make a CSV list with the extracted data.
The substrings of interest occur at known locations within each record. However, there are no unique identifiers (primary keys) within the data itself. It is simply a list of data where each "record" begins with a line starting in "01". Every subsequent line belongs to that same record, until the next "01". The presence of a given line might vary, but if present, data occurs at specific intervals.
The data looks like this:
Line1: 01253820RELEVANTSUBSTRING39ALSORELEVANT0990
Line2: 02999IRRELEVANT
Line3: 0420180101RELEVANTMONTHLYDATA000MORERELEVANTDATA8980
Line4: 0420190101FURTHERRELEVANTMONTHLYDATA
Line5: 12000003848982IRRELEVANT
Line6: 0100NEWRECORD8932000
Line7: 0420100101MORE
I have been able to successfully extract relevant substrings occurring after each "01" using the following code (partially included below):
static void PopulateList(){
using (StreamReader sr = new StreamReader(sourcePath))
{
string ctrl //control key - indicates a new record if "01"
List<TurbineModel> turbines = new List<TurbineModel>();
List<string> lines = File.ReadAllLines(sourcePath).ToList();
foreach (string line in lines)
{
if (line.Substring(0, 2) == "01")
{
ctrl = line.Substring(0, 2);
TurbineModel newWell = new TurbineModel();
newTurbine.Ctrl = ctrl;
turbines.Add(newTurbine);
}
}
}
This code is working fine. However, there are lines further down that begin with "04" which have other information that I have not been able to extract and group with the current "01" list. I can extract substrings from every line that begins with an "04", but I don't have any way to link each record's data to the "01" record that preceded it.
What I need the code to do is the following:
1) Arrive at an "01" in the data and set up a new record
2) Extract relevant info from "01" line (per code above)
3) Skip subsequent lines unless it reaches an "04"
4) If it reaches an "04", extract substrings from that line and group those extracted substrings with the "01" substrings
5) Continue scanning lines until it reaches a new "01", at which point it sets up a new record and starts again
6) Output everything to CSV
I have been unable to group the information together so that I know which "04" relates to which "01".
Any help you can provide is greatly appreciated. Let me know if I can clarify.
It seems to me that all you have to do is create a class that can store the data from the 01 line, and which can hold the relevant parts of the following lines.
Here's an example, where we loop through each line in the file, and if the line starts with "01, we create a new Item and add the line as it's Data (you could do some processing of the line contents instead to populate other properties). If the line doesn't start with "01" and we've already created an Item, then we add the line to the item's AssociatedLines property if it starts with "04" (you could also process the line in some way and add the relevant parts to the Item instead).
At the end, we have a list of Item objects that were each created from a line that begins with "01" and which contain all the lines after that until the next line that starts with "01".
First, the Item class:
public class Item
{
public string Data { get; set; }
public List<string> AssociatedData { get; set; } = new List<string>();
// This returns a comma-separated line representing this item
public string GetCsvString()
{
return $"{Data},{string.Join(",", AssociatedData)}";
}
}
And then the code that creates a list of these based on the file data:
public static List<Item> GetItems(string filePath)
{
var items = new List<Item>();
Item current = null;
foreach (var line in File.ReadAllLines(filePath))
{
if (line.StartsWith("01"))
{
// If there's already a current item, add it to our list
if (current != null) items.Add(current);
// Here we would parse the '01' line and set properties of the current item
current = new Item {Data = line};
}
else if (line.StartsWith("04"))
{
// Here we would parse the '04' line and set properties of the current item
current?.AssociatedData.Add(line);
}
}
// Add the final item to our list
if (current != null) items.Add(current);
return items;
}
And then the code that calls the method above would simply look like:
var items = GetItems(#"f:\public\temp\temp.txt");
Extracting an item to a CSV file would probably best be done by either overriding the ToString() method on the Item class or providing a GetCsvString() method that spits out the relevant data in the correct format. After which, you could write the items to a csv file like:
File.WriteAllLines(#"f:\public\temp\temp.csv", items.Select(item => item.GetCsvString()));
Give this a go, it's a "chunk reader" :) I have used something similar in the past. It may need some work, but it parses your sample into 2 "chunks".
namespace Solution
{
class Solution
{
static void Main(string[] args)
{
var reader = new ChunkReader();
Chunk chunk = null;
foreach (Chunk c in reader.Read(#"D:\test.txt"))
{
Console.WriteLine(c.Header);
}
Console.ReadKey();
}
}
internal class ChunkReader
{
public IEnumerable<Chunk> Read(string filePath)
{
Chunk currentChunk = null;
using (StreamReader reader = new StreamReader(File.OpenRead(filePath)))
{
string currentLine;
while ((currentLine = reader.ReadLine()) != null)
{
if (currentLine.StartsWith("01"))
{
if (currentChunk != null)
{
yield return currentChunk;
}
currentChunk = new Chunk();
currentChunk.Contents.Add(currentLine);
}
else
{
currentChunk?.Contents.Add(currentLine);
}
}
}
yield return currentChunk;
}
}
internal class Chunk
{
public Chunk()
{
Contents = new SortedSet<string>();
}
public SortedSet<string> Contents { get; }
public string Header
{
get
{
return Contents.FirstOrDefault(s => s.StartsWith("01"));
}
}
}
}
First of all, as some others have suggested, if your file is really large you should consider an alternative to File.ReadAllLines() as it can get costly. But since the question is not about that, I'm moving past that.
First, two dummy functions to mimic extracting your necessary data once you know if a line begins with either 01 or 04.
static string Extract01Data(string line)
{
return line;
}
static string Extract04Data(string line)
{
return line;
}
EDIT
Edited the answer to accommodate multiple lines that begin with 04 that come after the first 01 line:
And a simple class to hold your resulting data:
public class Record
{
public string OneInfo { get; set; }
public List<string> FourInfo { get; set; } = new List<string>();
}
Then, here's my code, with explanations in comments:
static void Main()
{
var file = #"C:\Users\gurudeniyas\Desktop\CobolData.txt";
var lines = File.ReadAllLines(file).ToList();
var records = new List<Record>();
for (var count = 0; count < lines.Count; count++)
{
var line = lines[count];
var firstTwo = line.Substring(0, 2);
// Iterate till we find a line that starts with 01
if (firstTwo == "01")
{
// Create a Record and add 01 line related data
var rec = new Record
{
OneInfo = Extract01Data(line)
};
// Here we iterate to find preceding lines that start with 03
// If we find them, extract 04 data and add as a record
// Break out of the loop if we find the next 01 line or EOF
do
{
count++;
if (count == lines.Count)
break;
line = lines[count];
firstTwo = line.Substring(0, 2);
if (firstTwo == "04")
{
rec.FourInfo.Add(Extract04Data(line));
}
} while (firstTwo != "01");
// If we found next 01, backtrack count by 1 so in the outer loop we can process that record again
if (firstTwo == "01")
{
count--;
}
records.Add(rec);
}
}
Console.ReadLine();
}
If the "04" always follows the 01 you can just add an else if as below, and then access the last item in your list (this will work because adding a item to a list adds it to the end).
foreach (string line in lines)
{
if (line.Substring(0, 2) == "01")
{
ctrl = line.Substring(0, 2);
TurbineModel newWell = new TurbineModel();
newTurbine.Ctrl = ctrl;
turbines.Add(newTurbine);
}
else if (line.Substring(0, 2) == "04")
{
var lastTurbine = turbines[turbines.Count - 1];
//do what you need to do with the "04" record monthly data here
}
}
Have you looked at using a finite state machine algorithm? Seems ideal for this.

Compare two Lists using Linq for partial matches

I tried looking through some of the other questions, but couldn't find any that did a partial match.
I have two List<string>
They have codes in them. One is a list of selected codes, one is a list of required codes. The entire code list is a tree though, so they have sub codes. An example would be
Code B
Code B.1
Code B.11
So lets say the Required code is B, but anything under it's tree will meet that requirement, so if the Selected codes are A and C the match would fail, but if one of the selected codes was B.1 it contains the partial match.
I just need to know if any of the selected codes partially match any of the required codes. Here is my current attempt at this.
//Required is List<string> and Selected is a List<string>
int count = (from c in Selected where c.Contains(Required.Any()) select c).Count();
The error I get is on the Required.Any() and it's cannot convert from bool to string.
Sorry if this is confusing, let me know if adding any additional information would help.
I think you need something like this:
using System;
using System.Collections.Generic;
using System.Linq;
static class Program {
static void Main(string[] args) {
List<string> selected = new List<string> { "A", "B", "B.1", "B.11", "C" };
List<string> required = new List<string> { "B", "C" };
var matching = from s in selected where required.Any(r => s.StartsWith(r)) select s;
foreach (string m in matching) {
Console.WriteLine(m);
}
}
}
Applying the Any condition on required in this way should give you the elements that match - I'm not sure if you should use StartsWith or Contains, that depends on your requirements.
If selected and required lists are large enough the following is faster than the accepted answer:
static void Main(string[] args)
{
List<string> selected = new List<string> { "A", "B", "B.1", "B.11", "C" };
List<string> required = new List<string> { "B", "C" };
required.Sort();
var matching = selected.Where(s =>
{
int index = required.BinarySearch(s);
if (index >= 0) return true; //exact match
index = ~index;
if (index == 0) return false;
return s.StartsWith(required[index - 1]);
});
foreach (string m in matching)
{
Console.WriteLine(m);
}
}
Given n = required.Count and m = required.Count the accepted answer algorithm complexity is O(n*m). However what I propose has a better algorithm complexity: O((n+m)*Log(n))
This query finds any match that exists in two lists. If a value exists in both lists, it returns true, otherwise false.
List<string> listString1 = new List<string>();
List<string> listString2 = new List<string>();
listString1.Add("A");
listString1.Add("B");
listString1.Add("C");
listString1.Add("D");
listString1.Add("E");
listString2.Add("C");
listString2.Add("X");
listString2.Add("Y");
listString2.Add("Z");
bool isItemExist = listString1.Any(x => listString2.Contains(x));

Loading entries from a list made from .csv file

I am trying to retrieve data from a series of lists that have been populated from a single .csv file
i have the entire list added to a Dictionary and abbreviations from "lol" speak
so far i have it able to search through the list/dictionary and determine whether the item that is searched for is present or not. All i want to do it to write the:
abbreviation - full meaning
into the console
Here is my code so far:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
namespace expanded_meanings
{
class Program
{
static void Main(string[] args)
{
Dictionary<string, string> lolspeak_dictionary = new Dictionary<string, string>();
var reader = new StreamReader(File.OpenRead(#"H:\twitter.csv"));
List<string> short_name = new List<string>();
List<string> longer_name = new List<string>();
int count=0;
string search = Console.ReadLine();
while (!reader.EndOfStream)
{
var line = reader.ReadLine();
var values = line.Split(',');
lolspeak.Add(values[0], values[1]);
short_name.Add(values[0]);
longer_name.Add(values[1]);
count = count + 1;
}
if (short_name.Contains(search))
{
Console.WriteLine("Item found");
}
else
Console.WriteLine("Not Found");
Console.ReadLine();
}
//if (short_name = user_search);
}
}
First, you do not need the short_name and long_name as those values are contained within the lolspeak_dictionary, You can access them by using the Keys and Values properties of a Dictionary.
As for searching for the abbreviation - full meaning you can simply use your current code as
if (lolspeak_dictionary.ContainsKey(search))
{
Console.WriteLine("{0} - {1}", search, lolspeak_dictionary[search]);
}
else {
Console.WriteLine("'{0}' - Not Found", search);
}
UPDATE:
The method call Console.WriteLine("'{0}' - Not Found", search); works by using substitution. The value of search, is placed in the spot of {0}. The means that {0} - Not Found if search is WOTR you will get WOTR - Not found.
In the case of Console.WriteLine("{0} - {1}", search, lolspeak_dictionary[search]);. If search is WOTA, you would get WOTA - Will of the Ancients.
Additional Resources
Dictionary MSDN
Keys MSDN
Values MSDN
Understanding Dictionary

Sorting information to output list

I'm new to programming and I thought it would be great to start with something a bit simple but useful for me and my girlfriend.
I would like to create a shopping list program that will take my items that I input into the textbox and then sort them based on defined groups. Then output that information in an easy to read list already categorized for easy shopping.
My question is this; How do I sort information that I put into a rich textbox? I have two rich textboxes and I would like to input information into one and then output that information to the other but have it sorted to my preferences.
Thank you in advance. :-)
Since you want to group them, I would suggest creating a small GroceryItem like this:
class GroceryItem
{
GroceryItem(string category, string name) {
Category = category;
ItemName = name;
}
public string Category {get;set;}
public string ItemName {get;set;}
}
Then you can easily parse from your first text box the items. Let's assume they look like this:
Vegies, Tomato
Meat, Lamb
Vegies, Potato
Meat, Chicken
Just read them all, split on , to get 2 parts for each, and create a new GroceryItem:
List<CategoryItem> shoppingList = new List<CategoryItem>();
foreach (var line in your_lines_collection)
{
var parts = some_line.Split(',');
shoppingList.Add(new GroceryITem(parts[0],parts[1]));
}
And last, but not least, once you have a list of those (shoppingList), you can use linq to sort to your heart content. Here's an example:
List<GroceryItem> shoppingList = new List<GroceryItem>();
List<string> groceries = new List<string>(){"veg, pot", "veg, tom", "meat, chicken", "meat, veal"};
foreach (var line in groceries)
{
var parts = line.Split(',');
shoppingList.Add(new GroceryItem(parts[0],parts[1]));
}
var sorted_list_by_ItemName =
from item in shoppingList
orderby item.ItemName
group item by item.Category into groups
select groups
;
foreach (var gr in sorted_list_by_ItemName)
{
Console.Out.WriteLine("[{0}] :", gr.Key);
foreach (var it in gr)
Console.Out.WriteLine(" {0}", it);
}
This will output:
[meat] :
meat , chicken
meat , veal
[veg] :
veg , pot
veg , tom
You then can just print this on your other textbox, or work with it as you wish :)
As per comments, here's the whole code for a console, just paste it into your visual studio, and it should work:
using System;
using System.Collections.Generic;
using System.Linq;
internal class Program
{
public static void Main(string[] args)
{
List<GroceryItem> shoppingList = new List<GroceryItem>();
List<string> groceries = new List<string>() { "veg, pot", "veg, tom", "meat, chicken", "meat, veal" };
foreach (var line in groceries)
{
var parts = line.Split(',');
shoppingList.Add(new GroceryItem(parts[0], parts[1]));
}
var sorted_list_by_ItemName =
from item in shoppingList
orderby item.ItemName
group item by item.Category into groups
select groups;
foreach (var gr in sorted_list_by_ItemName)
{
Console.Out.WriteLine("[{0}] :", gr.Key);
foreach (var it in gr)
Console.Out.WriteLine(" {0}", it);
}
Console.ReadKey();
}
public class GroceryItem
{
public GroceryItem(string category, string name)
{
Category = category;
ItemName = name;
}
public string Category { get; set; }
public string ItemName { get; set; }
public override string ToString()
{
return Category + " , " + ItemName;
}
}
}
To avoid an ongoing ping pong, if you have another question, just open a new one (if it's relevant). Otherwise, you can upvote,downvote, and mark as answered if this answered your question. :)
Well, if your first RichTextBox has each item separated by something known (e.g. NewLine), then it should be as straight forward as this:
var list = richTextBox1.Text
.Split(new[] { Environment.NewLine },
StringSplitOptions.RemoveEmptyEntries)
.Sort();
richTextBox2.Text = string.Join(Environment.NewLine, list.ToArray());
This will leverage the default sorting algorithm for the type. In this case string. So it will sort them alphabetically.

Categories

Resources