#c# #.net #console-application #txt
Вопрос:
Я работаю над задачей, которая покажет, сколько стран вступило в Европейский союз в 2004 году. Я также хотел бы получить названия стран, которые присоединились к нам в 2004 году. Я начал делать свою работу, но получаю только Кипр. Проблема в том, что в 2004 году к ней присоединились несколько стран. Как получить все названия стран, которые присоединились в 2004 году? Я выполнил свою задачу в консольном приложении (.NET Framework). Для этой задачи я использовал txt-файл, содержащий данные. Вот мой код:
class Program
{
static List<Country> joining = new List<Country>();
static void read()
{
string[] rows=File.ReadAllLines("EU.txt");
foreach (var item in rows)
{
joining.Add(new Country(item));
}
}
static void Main(string[] args)
{
read();
// how many countries:
Console.WriteLine($"{joining.Count(item =>item.date.Split('.')[1] == "05" )}countries joined.");
//names:
Console.WriteLine($"Country names:{joining.Find(item =>item.date.Split('.')[1] == "05" ).name}"); // !!! this code is bad
Console.ReadKey();
}
}
class Country
{
//Fields
public string date, name;
//ctor
public Country(string row)
{
name=row.Split(';')[0];
date = row.Split(';')[1];
}
}
EU.txt:
Австрия;1995.01.01 Бельгия;1958.01.01 Болгария;2007.01.01 Кипр;2004.05.01 Чехия;2004.05.01 Дания;1973.01.01 Соединенное Королевство;1973.01.01 Эстония;2004.05.01 Финляндия;1995.01.01 Франция;1958.01.01 Греция;1981.01.01 Нидерланды;1958.01.01 Хорватия;2013;07.01 Ирландия;1973.01.01 Польша;2004.05.01 Латвия;2004.05.01 Литва;2004.05.01 Люксембург;1958.01.01 Венгрия;2004.05.01 Мальта;2004.05.01 Германия;1958.01.01 Италия;1958.01.01 Португалия;1986.01.01 Румыния;2007.01.01 Испания;1986.01.01 Швеция;1995.01.01 Шловакия;2004.05.01 Шловения;2004.05.01
Комментарии:
1.
joining.Find(...)
найдете только первый пункт (Cyprus
в вашем случае).2. Вы хотите 2004 год или хотите май месяц? Потому что текст вопроса говорит одно, но код вопроса говорит другое.
3. Кроме того, НИКОГДА не публикуйте примеры данных в виде изображения.
Ответ №1:
Ну, joining.Find(...)
найдете только первый пункт ( Cyprus
в вашем случае). Вместо этого вы можете использовать Linq Where
. Пожалуйста, обратите внимание, что вы должны сравнивать с "2004"
(годом), а не с "05"
(месяцем):
using System.Linq;
...
// names:
var names = joining
.Where(item => item.date.Split('.')[0] == "2004")
.Select(item => item.name);
// let's join all the names by ", ":
Console.WriteLine($"Country names:{string.Join(", ", names)}");
Правка: Однако сравнение вроде item.date.Split('.')[1] == "2004"
выглядит некрасиво (почему я должен думать о строках при запросе дат?).
Позвольте Country
классу помочь самому себе (даты, имена и т.д.):
class Country {
public string Name {get;}
public DateTime JoinedDate {get;}
public Country(string row) {
if (row == null)
throw new ArgumentNullException(nameof(row));
string[] items = row.Split(';', 2);
if (items.Length < 2)
throw new FormatException("Invalid row format");
Name = items[0];
JoinedDate = DateTime.ParseExact(items[1], "yyyy.M.d");
}
public override string ToString() => Name;
}
затем дело доходит до Linq (мы запрашиваем EU.txt
файл):
static void Main(string[] args) {
List<Country> joined2004 = File
.ReadLines("EU.txt")
.Select(line => new Country(line))
.Where(country => country.JoinedDate.Year == 2004)
.ToList();
Console.WriteLine($"{joined2004.Count} countries joined.");
Console.WriteLine($"{string.Join(", ", joined2004)}")
}
Ответ №2:
Здесь много мелких изменений:
class Program
{
static List<Country> Countries;
// Use types and methods that avoid needing to load full sets into RAM all at once
// for as long as possible. That means IEnumerable rather than List and ReadLines()
// rather than ReadAllLines().
// It's also better for the read() function accept a value and return the result
static IEnumerable<Country> ReadCountries(string filePath)
{
// No need to allocate so much RAM via ReadAllLines()
// Better to just have one line in RAM at a time until everything is loaded
return File.ReadLines(filePath)
.Select(line => new Country(line));
}
static void Main(string[] args)
{
Countries = ReadCountries("EU.txt").ToList();
var JoinedIn2004 = Countries.Where(c => c.date.Year == 2004);
Console.WriteLine($"{JoinedIn2004.Count()} countries joined.nCountry name:");
// need to loop through the list to get all the names
foreach(var country in JoinedIn2004)
{
Console.WriteLine(country.name);
}
// Alternatively, if you really don't want to write a loop:
// Console.WriteLine(string.Join("n", JoinedIn2004));
Console.ReadKey(true);
}
}
class Country
{
// properties > fields
public string name {get;set;}
public DateTime date {get;set;} //Parse an actual DateTime for this!
//personally I lean towards a static builder method (Country.FromTextLine())
// for this, to decouple building the type from any specific file,
// but I also get it's overkill here.
public Country(string row)
{
var format = "yyyy.MM.dd";
var fields = row.Split(';');
name = fields[0];
date = DateTime.ParseExact(fields[1], format, null);
}
}
Ответ №3:
List<Country> result = joining.FindAll(item =>item.date.Split('.')[1] == "05");
Console.Write($"Country names:");
foreach(Country country in result)
{
Console.Write($"{country.name} ");
}
Console.WriteLine();