#c# #.net #vb.net #datatable #ienumerable
Вопрос:
У меня есть эти данные:
Указатель | Дата | Открыть | высокий | низкий | Закрыть | объем |
---|---|---|---|---|---|---|
1 | 01/03/17 | $212.61 | $213.35 | $211.52 | $212.80 | 96,708,880 |
2 | 01/04/17 | $213.16 | $214.22 | $213.15 | $214.06 | 83,348,752 |
3 | 01/05/17 | $213.77 | $214.06 | $213.02 | $213.89 | 82,961,968 |
Я пытаюсь использовать библиотеку Skender.stocks
https://daveskender.github.io/Stock.Индикаторы/руководство/
В образце на странице говорится только:
IEnumerable<Цитата> кавычки = <Цитата>Функция Mycustom();
Как я могу использовать DataTable в функции или приведении для возврата a IEnumerable<Quote>
?
Ответ №1:
Вам нужно будет:
- Выполните итерацию по строкам, доступным для данных
- Создайте новый экземпляр предложения
- Введите значения из строки в соответствующее свойство
- Добавьте цитату в
List(Of Quote)
С этого момента список будет вашим IEnumerable.
Вот пример:
Dim quotes As New List(Of Quote)()
For Each row As DataRow In MyDataTable.Rows
quotes.Add(New Quote() With {
.Date = Convert.ToDateTime(row.Item("Date")),
.Open = Convert.ToDecimal(row.Item("Open")),
.High = Convert.ToDecimal(row.Item("High")),
.Low = Convert.ToDecimal(row.Item("Low")),
.Close = Convert.ToDecimal(row.Item("Close")),
.Volume = Convert.ToDecimal(row.Item("Volume"))
})
Next
Живая демонстрация: https://dotnetfiddle.net/LgguWG
Это быстрый и грязный метод, если вы знаете, что каждая строка будет иметь значение для каждого столбца и каждый столбец может быть преобразован в соответствующий тип данных.
Если вы хотите немного уточнить его, вы можете настроить условные операторы, пытающиеся преобразовать значения, прежде чем устанавливать свойство цитаты, добавляемой в коллекцию.
Ответ №2:
Один из вариантов-создать свой собственный Quote
класс и добавить конструктор, который получает значения своих свойств из потока данных
private class MyQuote : Quote
{
public MyQuote(DataRow dr)
{
this.Date = (DateTime)dr["date"];
this.Open = (decimal)dr["open"];
this.High = (decimal)dr["high"];
this.Low = (decimal)dr["low"];
this.Close = (decimal)dr["close"];
this.Volume = (decimal)dr["volume"];
}
}
или реализация интерфейса
private class MyQuote : IQuote
{
public DateTime Date { get; set; }
public decimal Open { get; set; }
public decimal High { get; set; }
public decimal Low { get; set; }
public decimal Close { get; set; }
public decimal Volume { get; set; }
public MyQuote(DataRow dr)
{
this.Date = (DateTime)dr["date"];
this.Open = (decimal)dr["open"];
this.High = (decimal)dr["high"];
this.Low = (decimal)dr["low"];
this.Close = (decimal)dr["close"];
this.Volume = (decimal)dr["volume"];
}
}
Затем вы можете использовать некоторый LINQ, чтобы получить его из базы данных (то же самое для производного класса и интерфейса).
var quotes = dt.Select().Select(r => new MyQuote(r));
Комментарии:
1. Согласно документации по использованию пользовательских классов ( daveskender.github.io/Stock. Индикаторы/руководство/… ), рекомендуется реализовать интерфейс
IQuote
, а не наследоватьQuote
класс.2. @David не читал, спасибо, добавлена опция интерфейса
Ответ №3:
Огромное, огромное спасибо Дэвиду!!, полный код на c#, если он кому-то еще нужен, выглядит так:
Заполните таблицу данных….
using Skender.Stock.Indicators;
void makedt ()
{
dt = new DataTable();
dt.Clear();
dt.Columns.Add("Date");
dt.Columns.Add("Open");
dt.Columns.Add("High");
dt.Columns.Add("Low");
dt.Columns.Add("Close");
dt.Columns.Add("Volume");
DataRow _ravi = dt.NewRow();
_ravi["Date"] = DateTime.Now;
_ravi["Open"] = "500";
_ravi["High"] = "500";
_ravi["Low"] = "500";
_ravi["Close"] = "500";
_ravi["Volume"] = "500";
dt.Rows.Add(_ravi);
//_ravi.Delete();
_ravi = dt.NewRow();
_ravi["Date"] = DateTime.Now;
_ravi["Open"] = "600";
_ravi["High"] = "600";
_ravi["Low"] = "600";
_ravi["Close"] = "600";
_ravi["Volume"] = "600";
dt.Rows.Add(_ravi);
//_ravi.Delete();
_ravi = dt.NewRow();
_ravi["Date"] = DateTime.Now;
_ravi["Open"] = "700";
_ravi["High"] = "700";
_ravi["Low"] = "700";
_ravi["Close"] = "700";
_ravi["Volume"] = "700";
dt.Rows.Add(_ravi);
//_ravi.Delete();
_ravi = dt.NewRow();
_ravi["Date"] = DateTime.Now;
_ravi["Open"] = "800";
_ravi["High"] = "800";
_ravi["Low"] = "800";
_ravi["Close"] = "800";
_ravi["Volume"] = "800";
dt.Rows.Add(_ravi);
//_ravi.Delete();
_ravi = dt.NewRow();
_ravi["Date"] = DateTime.Now;
_ravi["Open"] = "900";
_ravi["High"] = "900";
_ravi["Low"] = "900";
_ravi["Close"] = "900";
_ravi["Volume"] = "900";
dt.Rows.Add(_ravi);
//_ravi.Delete();
}
запуск процедуры……
void method()
{
List<Quote> _quotes = new List<Quote>();
foreach (DataRow row in dt.Rows)
_quotes.Add(new Quote()
{
Date = Convert.ToDateTime(row["Date"]),
Open = Convert.ToDecimal(row["Open"]),
High = Convert.ToDecimal(row["High"]),
Low = Convert.ToDecimal(row["Low"]),
Close = Convert.ToDecimal(row["Close"]),
Volume = Convert.ToDecimal(row["Volume"])
});
string s = "";
foreach (var quote in _quotes)
{
s = s quote.Date.ToString() quote.Open.ToString() quote.High.ToString() quote.Low.ToString() quote.Close.ToString();
} // this for if only for check values
IEnumerable<Quote> quotes = _quotes;
IEnumerable<SmaResult> results = quotes.GetSma(2);
}
Комментарии:
1. Плохая практика кодирования, связанная с этим ответом
2. @Chestera, Возможно, было бы более полезно указать на то, что вы считаете неправильным.
3. Лучший способ поблагодарить кого-либо за переполнение стека-принять его ответ, щелкнув галочку (галочку) слева от его ответа. Это принесло бы Дэвиду несколько очков, помогло бы будущим читателям и даже дало бы вам 2 балла.
4. @Mary ops, я просматривал в очереди этот ответ и не заметил, что он собирался опубликовать здесь. Хорошо, я имею в виду, что на плохой практике в этом ответе много дублирования кода, и он нуждается в некотором рефакторинге