Эффективный способ разделения строк
У меня есть завершенная строка, как это
N:Pay in Cash++RGI:40++R:200++T:Purchase++IP:N++IS:N++PD:PC++UCP:598.80++UPP:0.00++TCP:598.80++TPP:0.00++QE:1++QS:1++CPC:USD++PPC:Points++D:Y++E:Y++IFE:Y++AD:Y++IR:++MV:++CP:~~ N:ERedemption++RGI:42++R:200++T:Purchase++IP:N++IS:N++PD:PC++UCP:598.80++UPP:0.00++TCP:598.80++TPP:0.00++QE:1++QS:1++CPC:USD++PPC:Points++D:Y++E:Y++IFE:Y++AD:Y++IR:++MV:++CP:
эта строка такая
- Это список PO (вариантов оплаты), которые разделены ~~
- этот список может содержать один или несколько OP
- PO содержит только пары Key-Value, которые разделены :
- пробелы обозначаются ++
Мне нужно извлечь значения для ключа "RGI" и "N".
Я могу сделать это через цикл, я хочу эффективный способ сделать это. любая помощь по этому вопросу.
Изменить: от ~ ~ до ~~
6 ответов
Слышали, я использовал регулярные выражения, и для разумного количества текста они хорошо преформировались.
static void Main(string[] args)
{
string str = @"N:Pay in Cash++RGI:40++R:200++T:Purchase++IP:N++IS:N++PD:PC++UCP:598.80++UPP:0.00++TCP:598.80++TPP:0.00++QE:1++QS:1++CPC:USD++PPC:Points++D:Y++E:Y++IFE:Y++AD:Y++IR:++MV:++CP:~ ~N:ERedemption++RGI:42++R:200++T:Purchase++IP:N++IS:N++PD:PC++UCP:598.80++UPP:0.00++TCP:598.80++TPP:0.00++QE:1++QS:1++CPC:USD++PPC:Points++D:Y++E:Y++IFE:Y++AD:Y++IR:++MV:++CP:";
System.Text.RegularExpressions.MatchCollection MC = System.Text.RegularExpressions.Regex.Matches(str,@"((RGI|N):.*?)\+\+");
foreach( Match Foundmatch in MC)
{
string[] s = Foundmatch.Groups[1].Value.Split(':');
Console.WriteLine("Key {0} Value {1} " ,s[0],s[1]);
}
}
Не знаю, является ли он более эффективным, чем RegEx, но вот альтернатива, использующая LINQ to Objects.
KeyValuePair<string, string>[] ns = (from po in pos.Split(new string[] { "~~" }, StringSplitOptions.RemoveEmptyEntries)
from op in po.Split(new string[] { "++" }, StringSplitOptions.RemoveEmptyEntries)
where op.StartsWith("N:") || op.StartsWith("RGI:")
let op_split = op.Split(':')
select new KeyValuePair<string, string>(op_split[0], op_split[1])).ToArray();
Я думаю, что вы должны попробовать регулярное выражение. Поскольку вы используете C#, ознакомьтесь с этой удобной шпаргалкой.NET RegEx.
Вы можете разобрать строку в словаре, а затем получить ваши значения...
string s = "N:Pay in Cash++RGI:40++R:200++";
// Replace "++" with ","
s.Replace("++",",");
// Divide all pairs (remove empty strings)
string[] tokens = s.Split(new char[] { ':', ',' }, StringSplitOptions.RemoveEmptyEntries);
Dictionary<string, string> d = new Dictionary<string, string>();
for (int i = 0; i < tokens.Length; i += 2)
{
string key = tokens[i];
string value = tokens[i + 1];
d.Add(key,value);
}
Вот попытка выполнить поиск по индексу: (я предпочитаю свое решение LINQ, которое я добавил)
string test = "N:Pay in Cash++RGI:40++R:200++T:Purchase++IP:N++IS:N++PD:PC++UCP:598.80++UPP:0.00++TCP:598.80++TPP:0.00++QE:1++QS:1++CPC:USD++PPC:Points++D:Y++E:Y++IFE:Y++AD:Y++IR:++MV:++CP:~ ~N:ERedemption++RGI:42++R:200++T:Purchase++IP:N++IS:N++PD:PC++UCP:598.80++UPP:0.00++TCP:598.80++TPP:0.00++QE:1++QS:1++CPC:USD++PPC:Points++D:Y++E:Y++IFE:Y++AD:Y++IR:++MV:++CP:";
string[] parts = test.Split(new string[] { "~ ~" }, StringSplitOptions.None);
var result = parts.Select(p => new
{
N = p.Substring(p.IndexOf("N:") + 2,
p.IndexOf("++") - (p.IndexOf("N:") + 2)),
RGI = p.Substring(p.IndexOf("RGI:") + 4,
p.IndexOf("++", p.IndexOf("RGI:")) - (p.IndexOf("RGI:") + 4))
});
Создает список из двух объектов со следующими значениями:
result = {{N = "Pay in Cash", RDI = 40}, {N = "ERedemption", RDI = 42}}
РЕДАКТИРОВАТЬ: РЕШЕНИЕ С ИСПОЛЬЗОВАНИЕМ LINQ
Я решил попробовать все это с помощью LINQ, и вот что я придумал:
string test = "N:Pay in Cash++RGI:40++R:200++T:Purchase++IP:N++IS:N++PD:PC++UCP:598.80++UPP:0.00++TCP:598.80++TPP:0.00++QE:1++QS:1++CPC:USD++PPC:Points++D:Y++E:Y++IFE:Y++AD:Y++IR:++MV:++CP:~ ~N:ERedemption++RGI:42++R:200++T:Purchase++IP:N++IS:N++PD:PC++UCP:598.80++UPP:0.00++TCP:598.80++TPP:0.00++QE:1++QS:1++CPC:USD++PPC:Points++D:Y++E:Y++IFE:Y++AD:Y++IR:++MV:++CP:";
var result = test.Split(new string[] { "~ ~" }, StringSplitOptions.None).
Select(m => m.Split(new string[] { "++" }, StringSplitOptions.None)).
Select(p => p.Select(i => i.Split(':')).
Where(o => o[0].Equals("N") || o[0].Equals("RGI")).
Select(r => new { Key = r[0], Value = r[1]}));
Он производит и массив для каждого элемента, который содержит пару Key Value только N и RGI.
result = {{{Key = "N", Value = "Pay in Cash"}, {Key = "RDI", Value = 40}},
{{Key = "N", Value = "ERedemption"}, {Key = "RDI", Value = 42}}}
Если вы хотите, вы можете удалить Where
и это будет включать в себя все они ключи и их ценности.
Использование string.Split()
на ":", чтобы извлечь пары ключ-значение.
Затем извлеките их по мере необходимости. Если позиции в строке не являются фиксированными, вам нужно будет искать каждый элемент в результате string[]
массив для определенного ключа.
Если вам нужно часто искать, я бы подумал разбить пары ключ-значение и поместить их в какой-нибудь словарь.