Использование
blockquote>functools.partial
считается более подходящим, чем использованиеlambda
для этого случая?«Улучшенный» - слишком сильное слово. Возможно, было бы правильно сказать, что
functools.partial
является «одним очевидным выбором» для простой привязки аргументов.Некоторые возможные преимущества
functools.partial
по сравнению сlambda
не вытекают из вышеприведенного предложения:
Как указал @AlexHall,
functools.partial
позволяет избежать ошибки позднего связывания , которая часто возникает, когда лямбда создается в цикле.
functools.partial
могут прояснить намерение некоторых читателей. (Это, очевидно, индивидуально, так как читатели с любым фоном FP обычно предпочитаютlambda
.)В CPython
functools.partial
может быть чуть-чуть быстрее, чемlambda
. ] потому что ему не нужно создавать фрейм стека Python и не нужно выполнять фактическое связывание; его оптимизированная реализация на C просто должна выполнить вызов объекта. Разница должна измеряться в каждом конкретном случае.
Хорошо, вот что мы делаем: открываем файл, читаем его построчно и разбиваем по табуляциям. Затем мы берем второе целое число и перебираем остальные, чтобы найти путь.
StreamReader reader = File.OpenText("filename.txt");
string line;
while ((line = reader.ReadLine()) != null)
{
string[] items = line.Split('\t');
int myInteger = int.Parse(items[1]); // Here's your integer.
// Now let's find the path.
string path = null;
foreach (string item in items)
{
if (item.StartsWith("item\\") && item.EndsWith(".ddj"))
path = item;
}
// At this point, `myInteger` and `path` contain the values we want
// for the current line. We can then store those values or print them,
// or anything else we like.
}
Как уже упоминалось, я настоятельно рекомендую использовать регулярное выражение (в System.Text) для выполнения такой работы.
В сочетании с таким надежным инструментом, как RegexBuddy , вы можете справиться с любыми сложными ситуациями синтаксического анализа текстовой записи, а также быстро получить результаты. Этот инструмент упрощает задачу.
Надеюсь, это поможет.
Вы можете сделать что-то вроде:
using (TextReader rdr = OpenYourFile()) {
string line;
while ((line = rdr.ReadLine()) != null) {
string[] fields = line.Split('\t'); // THIS LINE DOES THE MAGIC
int theInt = Convert.ToInt32(fields[1]);
}
}
Причина, по которой вы не нашли релевантного результата при поиске по запросу «форматирование», заключается в том, что выполняемая вами операция называется «синтаксический анализ».
Другое решение, на этот раз с использованием регулярных выражений:
using System.Text.RegularExpressions;
...
Regex parts = new Regex(@"^\d+\t(\d+)\t.+?\t(item\\[^\t]+\.ddj)");
StreamReader reader = FileInfo.OpenText("filename.txt");
string line;
while ((line = reader.ReadLine()) != null) {
Match match = parts.Match(line);
if (match.Success) {
int number = int.Parse(match.Group(1).Value);
string path = match.Group(2).Value;
// At this point, `number` and `path` contain the values we want
// for the current line. We can then store those values or print them,
// or anything else we like.
}
}
Это выражение немного сложное, поэтому здесь оно разбито:
^ Start of string
\d+ "\d" means "digit" - 0-9. The "+" means "one or more."
So this means "one or more digits."
\t This matches a tab.
(\d+) This also matches one or more digits. This time, though, we capture it
using brackets. This means we can access it using the Group method.
\t Another tab.
.+? "." means "anything." So "one or more of anything". In addition, it's lazy.
This is to stop it grabbing everything in sight - it'll only grab as much
as it needs to for the regex to work.
\t Another tab.
(item\\[^\t]+\.ddj)
Here's the meat. This matches: "item\<one or more of anything but a tab>.ddj"
Попробуйте регулярные выражения. Вы можете найти в своем тексте определенный узор и заменить его тем, что вам нужно. Я не могу дать вам точный код прямо сейчас, но вы можете проверить свои выражения, используя его.
Вы можете открыть файл и использовать StreamReader.ReadLine для чтения файла построчно. Затем вы можете использовать String.Split, чтобы разбить каждую строку на части (используйте разделитель \ t), чтобы извлечь второе число.
Поскольку количество элементов различается, вам нужно будет искать в строке шаблон 'item \ *. Ddj'.
Чтобы удалить элемент, вы можете (например) сохранить все содержимое файла в памяти и записывать новый файл, когда пользователь нажимает «Сохранить».
Один из способов, который я нашел действительно полезным в подобных ситуациях, - это пойти по старинке и использовать поставщика Jet OLEDB вместе с файлом schema.ini для чтения больших файлов с разделителями табуляцией. при использовании ADO.Net. Очевидно, что этот метод действительно полезен только в том случае, если вы знаете формат импортируемого файла.
public void ImportCsvFile(string filename)
{
FileInfo file = new FileInfo(filename);
using (OleDbConnection con =
new OleDbConnection("Provider=Microsoft.Jet.OLEDB.4.0;Data Source=\"" +
file.DirectoryName + "\";
Extended Properties='text;HDR=Yes;FMT=TabDelimited';"))
{
using (OleDbCommand cmd = new OleDbCommand(string.Format
("SELECT * FROM [{0}]", file.Name), con))
{
con.Open();
// Using a DataReader to process the data
using (OleDbDataReader reader = cmd.ExecuteReader())
{
while (reader.Read())
{
// Process the current reader entry...
}
}
// Using a DataTable to process the data
using (OleDbDataAdapter adp = new OleDbDataAdapter(cmd))
{
DataTable tbl = new DataTable("MyTable");
adp.Fill(tbl);
foreach (DataRow row in tbl.Rows)
{
// Process the current row...
}
}
}
}
}
Когда у вас есть данные в удобном формате, таком как таблица данных, фильтрация нужных данных становится довольно тривиальной.