@andrey_levushkin

C# — Как сделать выборку из текста?

В переменной имеется текст, например:
string a = "{"anchor":"aaabbbccc==","members":[{"userId":"111"},{"userId":"2222"},{"userId":"333"},{"userId":"444"}],"has_more":true}

(сегментов типа {"userId":"XXX"} может быть и больше)
Как сделать так, чтобы на выходе мы получили то что ниже?:

111
222
333
444

(либо в текстовом файле, либо в Text.Box)
У меня была идея сделать парсинг текста, ведь нужные мне места всегда находятся между {"userId":" и "}
То есть можно сделать цикл, который будет пробегать через текст этой переменной и выбирать всё что между {"userId":" и "}, помещая выражения в новые строки
Но как это сделать? Есть идейки? Спасибо заранее
  • Вопрос задан
  • 330 просмотров
Пригласить эксперта
Ответы на вопрос 2
mindtester
@mindtester Куратор тега C#
http://iczin.su/hexagram_48
https://www.newtonsoft.com/json

если вам предложат регулярки, стоит сравнивать производительность (регулярки не блещут скоростью upd все верно, простотой тоже, тривиальные случаи не считаем )))

сам бы скорее всего сделал в рукопашку, при условии что другие данные точно не нужны. при чем суть вы уже описали ;))) и по производительности, это наверняка самый быстрый вариант (upd )по производительности, а вот по реализации - зависит от навыков, кому то может быть проще newtonsoft (ну и см ленивый вариант, там тоже не производительность (но думаю и далеко не самый тормозной), но легко быстро набросать логику и легко ее оттестировать)

ps можно еще ленивый вариант - Split по
{"userId":"
тогда первый элемент отбрасываем, все остальные начинаются с искомой величины, надо только хвост
"} bla-bla-bla
отрубить

ps держите прототип, содержит все 3 упомянутые подхода, но перфоманс можно сравнить только на реально больших данных )).. (но на больших данных могут и баги полезть ;)

spoiler

вопрос понравился, и выдалось время.. хотя и не за 15 минут, врать не буду, часа полтора порядка 45 минут ушло на заковырки )) в основном с json (мало опыта)

upd и уже исправлено - была заготовка класса для частичной json выборки, но она не нужна

using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace parsejson111
{
    class Program
    {
        const string data = "{\"anchor\":\"aaabbbccc==\",\"members\":[{\"userId\":\"111\"},{\"userId\":\"2222\"},{\"userId\":\"333\"},{\"userId\":\"444\"}],\"has_more\":true}";
        // фишки замера заложены, но разница может проявиться только на больших объемах ))

        static void Main(string[] args)
        {
            Console.WriteLine("data:");
            Console.WriteLine(data);

            var sw = new Stopwatch();
            sw.Start();
            var ts = sw.Elapsed; // лень объявлять тип

            json();
            hand();
            lazy();

            sw.Stop();
            Console.WriteLine("press any key to continue...");
            Console.ReadKey();

            void json() // возможно существует более элегантный вариант. тут у меня опыта мало ))
            {
                sw.Reset();
                Console.WriteLine("... json");
                var j = JObject.Parse(data);
                var r = j["members"].Children().ToList();
                foreach (var u in r)
                {
                    var uid = JObject.Parse(u.ToString());
                    var id = uid["userId"].Value<string>();
                    Console.WriteLine(id);
                }
                ts = sw.Elapsed;
                Console.WriteLine($"\t{ts.Hours:00}:{ts.Minutes:00}:{ts.Seconds:00}.{ts.Milliseconds:000}");
            }

            void hand() // зато тут гарантирую - оптимизировать лучше не реально, и по перфомансу вряд ли можно лучше ))
            {
                sw.Reset();
                Console.WriteLine("... hand");
                var p = 0;
                while ((p = data.IndexOf("{\"userId\":\"", p)) > 0)
                {
                    p += 11; //длина шаблона. заодно избегаем риска зацикливания
                    var f = data.IndexOf("\"}", p);
                    Console.WriteLine(data.Substring(p, f - p));
                }
                ts = sw.Elapsed;
                Console.WriteLine($"\t{ts.Hours:00}:{ts.Minutes:00}:{ts.Seconds:00}.{ts.Milliseconds:000}");
            }

            void lazy()
            {
                sw.Reset();
                Console.WriteLine("... lazy");
                var t = data.Split(new string[] { "{\"userId\":\"" }, StringSplitOptions.RemoveEmptyEntries);
                for (var i = 1; i < t.Length; i++) // здесь и везде - обработка пустого множества на вашей совести
                {
                    var id = t[i].Split(new string[] { "\"}" }, StringSplitOptions.RemoveEmptyEntries);
                    Console.WriteLine(id[0]);
                }
                ts = sw.Elapsed;
                Console.WriteLine($"\t{ts.Hours:00}:{ts.Minutes:00}:{ts.Seconds:00}.{ts.Milliseconds:000}");
            }
        }
    }
}

Ответ написан
Комментировать
Регулярками разбирать не стоит, можно наступить на грабли.
Лучше разбирать при помощи System.Json или Json.NET (Newtonsoft).
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы