Задать вопрос
@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":" и "}, помещая выражения в новые строки
Но как это сделать? Есть идейки? Спасибо заранее
  • Вопрос задан
  • 338 просмотров
Подписаться 1 Простой Комментировать
Пригласить эксперта
Ответы на вопрос 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}");
            }
        }
    }
}

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

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

Похожие вопросы