Splitting data from an array and pulling specific data - c#

I think what i have to do is split and pull data to do the following:
I have created a class, with the following array and method getContactList. I need to create a method getFirstNames() and return all the first names from the address book into the variable firstNames in a Test class and display them on the console.
class ContactList
{
public String[] contactList =
{
"John, Smith, jsmith#nbcc.ca, (506) 555-1234",
"Frank, Sinatra, fsinatra#nbcc.ca, (506) 696-1234",
"Joan, Rivers, jrivers#nbcc.ca, (506) 696-5678",
"Freddy, Mercury, fmercury#nbcc.ca, (506) 653-1234",
"Freddy, Kruger, fkruger#nbcc.ca, (506) 658-1234"
};
public String[] getContactList()
{
return contactList;
}
public String getLastNames()
{
string lastnames = "";
return lastnames;
}
}
class Program
{
static void Main(string[] args)
{
ContactList firstNames = new ContactList();
Console.WriteLine(firstNames.getFirstNames());
Console.WriteLine();
Console.WriteLine("Press any key to exit.");
Console.ReadKey();
}

Yours isn't exactly the best approach, but to achieve what you want...
(assuming you want to separate the names by , )
public string getFirstNames(){
StringBuilder sb=new StringBuilder();
foreach(var x in contactList){
var tmp=x.Split(',');
sb.Append(tmp[0]);
sb.Append(",");
}
return sb.ToString();
}

Better design it this way:
class ContactList
{
string firstName, lastName, eMail, ContactNo;
//Properties (getters/setters for above attributes/fields
}
class ContactListHandler
{
public List<string> GetFirstNames(string[] contactsText)
{
List<string> stringList = new List<string>();
foreach (string s in contactsText)
{
var x = contactsText.split(',');
stringList.Add(x[0]);
}
return stringList;
}
//and other functions
}
Main()
{
ContactListHandler cHandler = new ContactListHandler();
List<string> contactsString = cHandler.GetFirstNames(//your string variable containing the contacts);
foreach(string s in contactsString)
{
Console.WriteLine(s);
}
}
Yes it has increased code but only for once, now you can use it in an Object-oriented way for any string,etc.

It's working I checked :) good luck with your development
using System.IO;
using System;
using System.Collections.Generic;
using System.Linq;
class Program
{
static void Main()
{
// Just to hold data
string[] data = new String[]{"John, Smith, jsmith#nbcc.ca, (506) 555-1234","Frank, Sinatra, fsinatra#nbcc.ca, (506) 696-1234","Joan, Rivers, jrivers#nbcc.ca, (506) 696-5678","Freddy, Mercury, fmercury#nbcc.ca, (506) 653-1234","Freddy, Kruger, fkruger#nbcc.ca, (506) 658-1234"};
// Create new contact list object
ContactList contacts = new ContactList(data);
// Call our method
contacts.PrintLastNames();
}
}
public class ContactList
{
// Declare properties
// google C# getter setter
private List<string> cList;
public List<string> CList{
get{ return cList; }
}
// Constructor
public ContactList(string[] _contactList)
{
// When creating new instance, take array of contacts and put into list
this.cList = _contactList.ToList();
}
// This will print out the names
public void PrintLastNames()
{
// Google lambda expression C# for more info on iteration
// With each string in cList, split by comas and use the first element
this.cList.ForEach( x => Console.WriteLine(x.Split(',')[0]));
// Use this for last names
//this.cList.ForEach( x => Console.WriteLine(x.Split(',')[1]));
}
// This will return names in list
public List<string> GetLastNames()
{
// Google List Collection Generic C# for more info
List<string> namesList = new List<string>();
this.cList.ForEach( x => namesList.Add( x.Split(',')[0] ));
return namesList;
}
}

Related

In my main, how to access string array in an array object? How to access parameter from constructor?

UML is attached. I want to create a readonly property of pre which is an array of string. When I create an object in the main and try to set name and pre it is showing me an error.
UML
using System;
class Unit
{
private string _name;
private string[] _pre;
public Unit(string name, string[] pre)
{
_name = name;
_pre = new string[2];
}
public string Name { get { return _name; } }
public string[] Pre { get { return _pre; } }
}
class Program
{
public static void DisplayInfo(Unit[] _u)
{
for (int i = 0; i < 2; i++)
{
Console.WriteLine(_u[i].Name + _u[i].Pre);
}
}
static void Main(string[] args)
{
Unit[] unitarraytest = new Unit[2];
unitarraytest[0] = new Unit("test 1", "test 3");
unitarraytest[1] = new Unit("test 2", "test 4");
DisplayInfo(unitarraytest);
}
}
Your example makes little sense. You Unit constructor takes a parameter for "Pre", but immediately throws it away and allocates a new empty string array instead. It should probably be written like
class Unit
{
public Unit(string name, string[] pre)
{
Name = name;
Pre = pre;
}
public string Name { get;}
public string[] Pre { get;}
}
When creating Unit objects you actually need to create an array for the "Pre" parameter. Like new Unit("Name", new []{"pre1", "pre2"});
And when outputting the strings you need to access the individual strings in the array, or combine them to a larger string, for example like Console.WriteLine(_u[i].Name + string.Join(" , ", _u[i].Pre));

How to properly access object's List<> value in C#?

I am trying to get the object value but I don't know how to do it. I'm new to C# and its giving me syntax error. I want to print it separately via the method "PrintSample" How can I just concatenate or append the whatData variable . Thank you.
PrintSample(getData, "name");
PrintSample(getData, "phone");
PrintSample(getData, "address");
//Reading the CSV file and put it in the object
string[] lines = File.ReadAllLines("sampleData.csv");
var list = new List<Sample>();
foreach (var line in lines)
{
var values = line.Split(',');
var sampleData = new Sample()
{
name = values[0],
phone = values[1],
address = values[2]
};
list.Add(sampleData);
}
public class Sample
{
public string name { get; set; }
public string phone { get; set; }
public string adress { get; set; }
}
//Method to call to print the Data
private static void PrintSample(Sample getData, string whatData)
{
//THis is where I'm having error, how can I just append the whatData to the x.?
Console.WriteLine( $"{getData. + whatData}");
}
In C# it's not possible to dynamically evaluate expression like
$"{getData. + whatData}"
As opposed to languages like JavaScript.
I'd suggest to use rather switch expression or Dictionary<string, string>
public void PrintData(Sample sample, string whatData)
{
var data = whatData switch
{
"name" => sample.name,
"phone" => sample.phone,
"address" => sample.address
_ => throw new ArgumentOutOfRangeException(nameof(whatData)),
};
Console.WriteLine(data);
}
I'm not sure what you are trying to achieve. Perhaps this will help you:
private static void PrintSample(Sample getData, string whatData)
{
var property = getData.GetType().GetProperty(whatData);
string value = (string)property?.GetValue(getData) ?? "";
Console.WriteLine($"{value}");
}
What PO really needs is
private static void PrintSamples(List<Sample> samples)
{
foreach (var sample in samples)
Console.WriteLine($"name : {sample.name} phone: {sample.phone} address: {sample.address} ");
}
and code
var list = new List<Sample>();
foreach (var line in lines)
{
......
}
PrintSamples(list);
it is radicolous to use
PrintSample(getData, "name");
instead of just
PrintSample(getData.name)
You can do this using reflection. However, it's known to be relatively slow.
public static void PrintSample(object getData, string whatData)
{
Console.WriteLine( $"{getData.GetType().GetProperty(whatData).GetValue(getData, null)}");
}

sort custom array list with a specific field

i would like to sort by postal address but i am unable to i have seen some Linq functions tried them but i can't seem to get all the required parameters needed.
for example i saw this one example
list.Sort((p, q) => p.Category.CompareTo(q.Category)); /*has and error that says cannot convert lamba expressions to type '|Comparer' because it is not a delegate*/
but i dont seem to understand how to use it.
MyCustomList.cs
class MyCustomList
{
private string name;
private string postalAddress;
public MyCustomList(string name, string postalAddress)
{
this.name = name;
this.postalAddress = postalAddress;
}
//getters and setters
public string Name
{
get
{
return name;
}
set
{
name = value;
}
}
public string PostalAddress
{
get
{
return postalAddress;
}
set
{
postalAddress = value;
}
}
}
Form1.cs
ArrayList list = new ArrayList();
list.Add(new MyCustomList("A somename","A Fake Postal Address");
list.Add(new MyCustomList("B somename","B Fake Postal Address");
list.Sort(); // Sort by Postal adress
Do you really need to use ArrayList?
It's a relic from the pre-generics days of .NET, and you should really be using an implementation of IEnumerable<T> where possible e.g. List<T>.
LINQ operates on IEnumerable<T>, so won't work with your ArrayList, and the method you are looking for is OrderBy or OrderByDescending.
Example:
var list = new List<MyCustomList>();
list.Add(new MyCustomList("A somename","A Fake Postal Address"));
list.Add(new MyCustomList("B somename","B Fake Postal Address"));
list.OrderBy(cl => cl.Postcode); // Sort by Postal address
First stop using ArrayList - its as good as obsolete.
Either using Array like this
var list = MyCustomList[2];
list[0] = new MyCustomList(...
list[1] = new MyCustomList(....
or use something like the List<T> class
var list = new List<MyCustomList>();
list.Add(new MyCustomList(...
list.Add(new MyCustomList(...
If you use array then the Sort function that takes an instance of Comparison<T> is static
see the documentation here https://learn.microsoft.com/en-us/dotnet/api/system.array.sort?view=netframework-4.8#System_Array_Sort__1___0___System_Comparison___0__
you need to call it like so:
Array.Sort(list, (a,b) => a.PostalAddress.CompareTo(b.PostalAddress))
or use linq on your List or Array and use OrderBy
var orderedList = list.OrderBy(a => a.PostalAddress);
Already approved by many https://stackoverflow.com/a/57371579/6923146
For order wise sorting with a specific field in c# using linq
list = list.OrderByDescending(x => x.Name).ToList();
list = list.OrderBy(x => x.Name).ToList();
//list.OrderBy(x => x.YourClassSpecificField).ToList()
Example:
please try to run following code in fiddle :
using System;
using System.Collections.Generic;
using System.Linq;
public class Program
{
public static void Main()
{
List<MyCustomList> list = new List<MyCustomList>();
list.Add(new MyCustomList("A somename", "A Fake Postal Address"));
list.Add(new MyCustomList("B somename", "B Fake Postal Address"));
//list.Sort();
Console.WriteLine("descending order");
list = list.OrderByDescending(x => x.Name).ToList();
foreach (MyCustomList o in list)
{
Console.WriteLine(o.Name + " -- " + o.PostalAddress );
}
Console.WriteLine("ascending order");
list = list.OrderBy(x => x.Name).ToList();
foreach (MyCustomList o in list)
{
Console.WriteLine(o.Name + " -- " + o.PostalAddress );
}
}
public class MyCustomList
{
private string name;
private string postalAddress;
public string Name
{
get { return name; }
set { name = value; }
}
public string PostalAddress
{
get { return postalAddress; }
set { postalAddress = value; }
}
public MyCustomList(string name, string postalAddress)
{
this.name = name;
this.postalAddress = postalAddress;
}
}
}

Text file parsing using helper class

I have a text file having list of movie names and its parts as below:
xxx, Author1, v6
the net, author1, v7
xxx, author3, v10
DDLJ, author3, v11
the fire, author5, v6
the health, author1, v8
the health, author7, v2
the hero, author9, v11
the hero, author8, v3
I would like to get most recent version of movie name. In this case it should return "DDLJ" and "the hero".
This is what I have tried:
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text.RegularExpressions;
namespace ProgramNamespace
{
public class Program
{
public static List<String> processData(IEnumerable<string> lines)
{
Dictionary<string, int> keyValuePairs = new Dictionary<string, int>();
foreach (var item in lines)
{
string[] readsplitted = item.Split(',');
keyValuePairs.Add(readsplitted[0], Convert.ToInt32(
Regex.Replace(readsplitted[2], "[^0-9]+", string.Empty)));
}
//List<String> retVal = new List<String>();
return retVal;
}
static void Main(string[] args)
{
try
{
List<String> retVal = processData(File.ReadAllLines(#"D:\input.txt"));
File.WriteAllLines(#"D:\output.txt", retVal);
}
catch (IOException ex)
{
Console.WriteLine(ex.Message);
}
}
}
}
Note that, if required I would like to add a helper class.
EDIT: version for duplicated keys
I rewrote the first solution I gave to take duplicated data into account. The trick is adding a progressive number before the key and separating it with an underscore: this way every key will be unique.
E.g. you will have your Dictionary filled like this:
"1_xxx", 6
"2_the net", 7
"3_xxx", 10
"4_DDLJ", 11
...
Then I remove the number (and the underscore) before providing a result.
public static List<String> processData(IEnumerable<string> lines)
{
var keyValuePairs = new Dictionary<string, int>();
int Position = 0;
foreach (var item in lines)
{
Position++;
string[] readsplitted = item.Split(',');
keyValuePairs.Add(Position.ToString() +"_" + readsplitted[0], Convert.ToInt32(Regex.Replace(readsplitted[2], "[^0-9]+", string.Empty)));
}
var MaxVersion = keyValuePairs.Values.OrderByDescending(f => f).First();
return keyValuePairs.Where(f => f.Value == MaxVersion).Select(f => string.Join("_", f.Key.Split('_').Skip(1))).ToList();
}
More in detail:
keyValuePairs.Values will return just the version numbers
.OrderByDescending(f => f).First() will sort the version numbers in descending order and pick the first, i.e. the highest
keyValuePairs.Where(f => f.Value == MaxVersion) will select the key-value pairs corresponding to the highest version above
.Select(f => f.Key) will give you the keys of your Dictionary, i.e. the titles
This way you will also keep your Dictionary; if you are doing this one time and you don't need to expand your code or reuse your models, you won't have to create other classes or make it more complicated than necessary.
For these kinds of tasks I usually prefer to create a class that represents the data we're collecting, and give it a TryParse method that will create an instance of the class based on a line of data:
public class MovieInfo
{
public string Name { get; set; }
public string Author { get; set; }
public int Version { get; set; }
public static bool TryParse(string input, out MovieInfo result)
{
result = null;
if (input == null) return false;
var parts = input.Split(',');
int version;
if (parts.Length == 3 &&
int.TryParse(parts[2].Trim().TrimStart('v'), out version))
{
result = new MovieInfo
{
Name = parts[0],
Author = parts[1],
Version = version
};
}
return result != null;
}
public override string ToString()
{
return $"{Name} (v{Version}) - {Author}";
}
}
Then it's just a matter of reading the file, creating a list of these classes, and getting all that have the highest number:
public static List<MovieInfo> processData(IEnumerable<string> lines)
{
if (lines == null) return null;
var results = new List<MovieInfo>();
foreach (var line in lines)
{
MovieInfo temp;
if (MovieInfo.TryParse(line, out temp))
{
results.Add(temp);
}
}
var maxVersion = results.Max(result => result.Version);
return results.Where(result => result.Version == maxVersion).ToList();
}
For example:
private static void Main()
{
var lines = new List<string>
{
"xxx, Author1, v6",
"the net, author1, v7",
"xxx, author3, v10",
"DDLJ, author3, v11",
"the fire, author5, v6",
"the health, author1, v8",
"the health, author7, v2",
"the hero, author9, v11",
"the hero, author8, v3",
};
var processed = processData(lines);
foreach (var movie in processed)
{
// Note: this uses the overridden ToString method. You could just do 'movie.Name'
Console.WriteLine(movie);
}
GetKeyFromUser("\nDone!! Press any key to exit...");
}
Output
This is how I would do it. This accounts for getting all the movie names that where the max version is the same.
public static List<String> processData(string fileName)
{
var lines = File.ReadAllLines(fileName);
var values = lines.Select(x =>
{
var readsplitted = x.Split(',');
return new { Name = readsplitted[0], Verison = int.Parse(readsplitted[2].Replace("v", string.Empty))};
});
var maxValue= values.Max(x => x.Verison);
return values.Where(v => v.Verison == maxValue)
.Select(v => v.Name)
.ToList();
}
static void Main(string[] args)
{
try
{
List<String> retVal = processData(#"D:\output.txt");
}
catch (IOException ex)
{
Console.WriteLine(ex.Message);
}
}
create a Movie class in order to initialize objects for each row that represents a movie.
split the whole string passed to processData() first by new line that by ','.
extract the number of the version of each movie (sperate it from "v") see: extractNumberFromString() method.
find the max version number and get (using linq query) all the movies that share the maximum version number.
public static List<Movie> processData(string s)
{
// list to store all movies
List<Movie> allmovies = new List<Movie>();
// first split by new line
var splitbynewline = s.Split('\n');
// split by ',' and initilize object
foreach (var line in splitbynewline)
{
var moviestring = line.Split(',');
// create new movie object
Movie obj = new Movie { Name = moviestring[0], Author = moviestring[1], Version = moviestring[2] };
obj.VersionNumber = extractNumberFromString(moviestring[2]);
allmovies.Add(obj);
}
// get the max version number
double maxver = allmovies.Max(x => x.VersionNumber);
// set and returen list that containes all movies with max version
List<Movie> result = allmovies.Where(x => x.VersionNumber == maxver).ToList();
return result;
}
/// <summary>
///
/// convert number that exist in a string to an int32 for example sdfdf43gn will return as 43
/// </summary>
/// <param name="value">string that contains inside him as digits</param>
/// <returns>int32</returns>
public static double extractNumberFromString(string value)
{
string returnVal = string.Empty;
System.Text.RegularExpressions.MatchCollection collection = System.Text.RegularExpressions.Regex.Matches(value, "\\d+");
foreach (System.Text.RegularExpressions.Match m in collection)
{
returnVal += m.ToString();
}
return Convert.ToDouble(returnVal);
}
public class Movie
{
public string Name;
public String Author;
public string Version;
public double VersionNumber;
}

Iterating through a list via a method call

I am entering code into a list. However, when I try to iterate through the code in a method call, nothing is being returned.
The problem code is found in "public class iterating". I am not sure why it won't execute.
Basically, I would like someone to enter information. Once the information has been entered, I would then like the user to iterate through the list via a method call.
using System;
using System.Text.RegularExpressions;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
public class Iterating
{
List<String> employees = new List<String>();
public void Test2()
{
//This is where I am trying to iterate//
for (int i = 0; i < employees.Count; i++)
{
Console.WriteLine(employees[i]);
}
}
}
public class Testing
{
public void Test1()
{
while (true)
{
List<String> employees = new List<String>();
Regex regex = new Regex(#"((.{5})-\d{2,5}-\d{2,5})|(#.*.com)");
Console.WriteLine("Please enter an e-mail");
string input = Console.ReadLine();
if(string.Equals(input, "quit", StringComparison.OrdinalIgnoreCase))
{
Console.WriteLine("You have quit the program");
break;
}
else if (match.Success)
{
Console.WriteLine(match.Value);
employees.Add(match.Value);
}
}
}
}
public class Program
{
public static void Main()
{
Testing T1 = new Testing();
T1.Test1();
Iterating I1 = new Iterating();
I1.Test2();
}
}
You don't get any output since
Every loop in the collection stage uses a new employees list.
Your two classes do not share the same employees list - they each have their own separate list.
If you want the iterating class to print the contents of a list, you need to pass it the list in question.
A partial example:
public class Program {
public static void Main() {
List<String> employees = new List<String>();
Testing T1 = new Testing();
T1.Test1(employees);
Iterating I1 = new Iterating();
I1.Test2(employees);
}
}
You would modify your test methods to use the passed list rather than create new ones
public class Iterating {
List<String> employees = new List<String>();
public void Test2()
{
//This is where I am trying to iterate//
for (int i = 0; i < employees.Count; i++)
{
Console.WriteLine(employees[i]);
}
}
}
employees is always empty since this doesn't have anything to do with Testing.employees you might want to remove it and pass the list into Test2 or into the constructor.
Also, Testing.employees should be outside the while look
You can redesign your class like this
public class Iterating
{
public void Test2(List<String> employees)
{
//This is where I am trying to iterate//
for (int i = 0; i < employees.Count; i++)
{
Console.WriteLine(employees[i]);
}
}
}
public class Testing
{
public List<String> Test1()
{
List<String> employees = new List<String>();//this should be outside the while loop
while (true)
{
Regex regex = new Regex(#"((.{5})-\d{2,5}-\d{2,5})|(#.*.com)");
Console.WriteLine("Please enter an e-mail");
string input = Console.ReadLine();
if(string.Equals(input, "quit", StringComparison.OrdinalIgnoreCase))
{
Console.WriteLine("You have quit the program");
break;
}
else if (match.Success)
{
Console.WriteLine(match.Value);//where is the match var
employees.Add(match.Value);//where is the match var
}
}
return employees;
}
}
public class Program
{
public static void Main()
{
Testing T1 = new Testing();
var employees = T1.Test1();
Iterating I1 = new Iterating();
I1.Test2(employees);
}
}

Categories

Resources