Предполагая, что оператор «break» в вашем цикле for означает, что вам нужна информация только о первом изображении, попробуйте:
import pydicom
import os
import csv
data_dir = 'C:\\Users\\dmgop\\Personal\\TE Project-Pneumonia\\stage_1_test_images_dicom'
patients = os.listdir(data_dir)
with open('file.csv','w') as myfile:
writer = csv.writer(myFile)
# patients[0] means get the first filename, no need for the for loop
lung = pydicom.dcmread(os.path.join(data_dir, patients[0]))
print(lung.formatted_lines)
# pay attention to the function_call --> formatted_lines()
writer.writerows(lung.formatted_lines())
Посмотрите документы Pydicom для FileDataset который является типом возврата для метода dcmread.
Если вы хотите записать данные для всех файлов в каталоге, попробуйте следующее:
import pydicom
import os
import csv
data_dir = 'C:\\Users\\dmgop\\Personal\\TE Project-Pneumonia\\stage_1_test_images_dicom'
patients = os.listdir(data_dir)
with open('file.csv','w') as myfile:
writer = csv.writer(myfile)
for patient in patients:
if patient.lower().endswith('.dcm'):
lung = pd.dcmread(os.path.join(data_dir, patient))
writer.writerows(lung.formatted_lines())
Также взгляните на последнюю часть этого параграфа об использовании 'with open () как '
Разделенный следующим regex шаблоном
string[] items = System.Text.RegularExpressions.Split(text, ";(?=\w+:)");
Править: лучше можно принять более специальные символы на название протокола.
string[] items = System.Text.RegularExpressions.Split(text, ";(?=[^;:]+:)");
Править: С обновленной информацией этот ответ, конечно, не добьется цели - но это все еще потенциально полезно, таким образом, я оставлю его здесь.
У Вас всегда будет три части, и Вы просто хотите разделить на первых двух точках с запятой?
Если так, просто используйте перегрузку Разделения, которое позволяет Вам указать количество подстрок для возврата:
string[] bits = text.Split(new char[]{';'}, 3);
Позвольте мне предложить создать регулярное выражение
(smtp|SMTP|X400|X500):((?!smtp:|SMTP:|X400:|X500:).)*;?
или протокол меньше
.*?:((?![^:;]*:).)*;?
другими словами, найдите что-либо, что запускается с одного из Ваших протоколов. Соответствуйте двоеточию. Затем продолжите соответствовать символам, пока Вы не соответствуете одному из своих протоколов. Конец с точкой с запятой (дополнительно).
Можно затем проанализировать через список разделения соответствий на ':' и у Вас будут свои протоколы. Дополнительно, если Вы хотите добавить протоколы, просто добавьте их к списку.
Вероятно, однако Вы собираетесь хотеть указать все это как нечувствительное к регистру и только перечислить протоколы в их прописных или строчных версиях.
Версия протокола меньше не заботится, каковы названия протоколов. Это просто находит их все равно, путем соответствия всему до, но, исключая строку, сопровождаемую двоеточием или точкой с запятой.
http://msdn.microsoft.com/en-us/library/c1bs0eda.aspx проверяет там, можно указать количество разделений, которые Вы хотите. таким образом в Вашем случае Вы сделали бы
string.split(new char[]{';'}, 3);
Не самое быстрое при выполнении этого много, но это будет работать на все случаи, которым я верю.
string input1 = "smtp:jblack@test.com;SMTP:jb@test.com;X400:C=US;A= ;P=Test;O=Exchange;S=Jack;G=Black;";
string input2 = "X400:C=US;A= ;P=Test;O=Exchange;S=Jack;G=Black;;smtp:jblack@test.com;SMTP:jb@test.com";
Regex splitEmailRegex = new Regex(@"(?<key>\w+?):(?<value>.*?)(\w+:|$)");
List<string> sets = new List<string>();
while (input2.Length > 0)
{
Match m1 = splitEmailRegex.Matches(input2)[0];
string s1 = m1.Groups["key"].Value + ":" + m1.Groups["value"].Value;
sets.Add(s1);
input2 = input2.Substring(s1.Length);
}
foreach (var set in sets)
{
Console.WriteLine(set);
}
Console.ReadLine();
Конечно, многие будут требовать Regex: Теперь у Вас есть две проблемы. Может даже быть лучший ответ regex, чем это.
Вы могли всегда разделять на двоеточии и иметь немного логики для захвата ключа и значения.
string[] bits = text.Split(':');
List<string> values = new List<string>();
for (int i = 1; i < bits.Length; i++)
{
string value = bits[i].Contains(';') ? bits[i].Substring(0, bits[i].LastIndexOf(';') + 1) : bits[i];
string key = bits[i - 1].Contains(';') ? bits[i - 1].Substring(bits[i - 1].LastIndexOf(';') + 1) : bits[i - 1];
values.Add(String.Concat(key, ":", value));
}
Протестированный это с обоими из Ваших образцов и это хорошо работает.
Это поймало мое любопытство.... Таким образом, этот код на самом деле делает задание, но снова, хочет привести в порядок :)
Моя заключительная попытка - прекращает изменять то, в чем Вы нуждаетесь;=)
static void Main(string[] args)
{
string fneh = "X400:C=US400;A= ;P=Test;O=Exchange;S=Jack;G=Black;x400:C=US400l;A= l;P=Testl;O=Exchangel;S=Jackl;G=Blackl;smtp:jblack@test.com;X500:C=US500;A= ;P=Test;O=Exchange;S=Jack;G=Black;SMTP:jb@test.com;";
string[] parts = fneh.Split(new char[] { ';' });
List<string> addresses = new List<string>();
StringBuilder address = new StringBuilder();
foreach (string part in parts)
{
if (part.Contains(":"))
{
if (address.Length > 0)
{
addresses.Add(semiColonCorrection(address.ToString()));
}
address = new StringBuilder();
address.Append(part);
}
else
{
address.AppendFormat(";{0}", part);
}
}
addresses.Add(semiColonCorrection(address.ToString()));
foreach (string emailAddress in addresses)
{
Console.WriteLine(emailAddress);
}
Console.ReadKey();
}
private static string semiColonCorrection(string address)
{
if ((address.StartsWith("x", StringComparison.InvariantCultureIgnoreCase)) && (!address.EndsWith(";")))
{
return string.Format("{0};", address);
}
else
{
return address;
}
}
Попробуйте эти regexes. Можно извлечь то, что Вы ищете использование именованных групп.
X400:(?<X400>.*?)(?:smtp|SMTP|$)
smtp:(?<smtp>.*?)(?:;+|$)
SMTP:(?<SMTP>.*?)(?:;+|$)
Удостоверьтесь при построении их, Вы указываете нечувствительный к регистру. Они, кажется, работают с образцами, которые Вы дали
Много попыток. Здесь является моим ;)
string src = "smtp:jblack@test.com;SMTP:jb@test.com;X400:C=US;A= ;P=Test;O=Exchange;S=Jack;G=Black;";
Regex r = new Regex(@"
(?:^|;)smtp:(?<smtp>([^;]*(?=;|$)))|
(?:^|;)x400:(?<X400>.*?)(?=;x400|;x500|;smtp|$)|
(?:^|;)x500:(?<X500>.*?)(?=;x400|;x500|;smtp|$)",
RegexOptions.IgnoreCase | RegexOptions.IgnorePatternWhitespace);
foreach (Match m in r.Matches(src))
{
if (m.Groups["smtp"].Captures.Count != 0)
Console.WriteLine("smtp: {0}", m.Groups["smtp"]);
else if (m.Groups["X400"].Captures.Count != 0)
Console.WriteLine("X400: {0}", m.Groups["X400"]);
else if (m.Groups["X500"].Captures.Count != 0)
Console.WriteLine("X500: {0}", m.Groups["X500"]);
}
Это находит весь smtp, x400 или адреса x500 в строке в любом порядке появления. Это также определяет тип адреса, готового к последующей обработке. Появление текста smtp, x400 или x500 в самих адресах не нарушит шаблон.
Это работает!
string input =
"smtp:jblack@test.com;SMTP:jb@test.com;X400:C=US;A= ;P=Test;O=Exchange;S=Jack;G=Black;";
string[] parts = input.Split(';');
List<string> output = new List<string>();
foreach(string part in parts)
{
if (part.Contains(":"))
{
output.Add(part + ";");
}
else if (part.Length > 0)
{
output[output.Count - 1] += part + ";";
}
}
foreach(string s in output)
{
Console.WriteLine(s);
}
Сделайте точку с запятой (;) разделите и затем цикл по результату, повторно комбинируя каждый элемент, где нет никакого двоеточия (:) с предыдущим элементом.
string input = "X400:C=US;A= ;P=Test;O=Exchange;S=Jack;G="
+"Black;;smtp:jblack@test.com;SMTP:jb@test.com";
string[] rawSplit = input.Split(';');
List<string> result = new List<string>();
//now the fun begins
string buffer = string.Empty;
foreach (string s in rawSplit)
{
if (buffer == string.Empty)
{
buffer = s;
}
else if (s.Contains(':'))
{
result.Add(buffer);
buffer = s;
}
else
{
buffer += ";" + s;
}
}
result.Add(buffer);
foreach (string s in result)
Console.WriteLine(s);
вот другое возможное решение.
string[] bits = text.Replace(";smtp", "|smtp").Replace(";SMTP", "|SMTP").Replace(";X400", "|X400").Split(new char[] { '|' });
биты [0], биты [1] и биты [2] будут затем содержать эти три части в порядке от Вашей исходной строки.