2

Есть массив переменного размера, например:

string[] elements_1;
elements_1[0] = "17-24 36-41 53-58 138-143 155";
elements_1[1] = "13-16 32 49-52 66-69";
elements_1[2] = "13-16 32-35 49-52 66 83 100-103";
...

Как из [i]-го элемента массива вытащить все числа с учетом интервалов и поместить в двумерный массив int [i, j] RESULT, в котором i=i первого массива, j содержит соответствующий массив полученных чисел?

pucher
  • 157
  • 2
  • 12

3 Answers3

4

Одна строчка парсится в числовую последовательность следующим кодом:

.Split().Select(s => Array.ConvertAll(s.Split('-'), int.Parse)).SelectMany(d => Enumerable.Range(d.First(), d.Last() - d.First() + 1))

Пример работы: https://ideone.com/mtqXpo

  • Прикольный способ :) Понял, как обошёлся с range. – Qwertiy Jan 31 '18 at 21:14
  • Вместо Array.ConvertAll(s.Split('-'), int.Parse) можно просто s.Split('-').Select(int.Parse), получится то же самое. – VladD Jan 31 '18 at 21:58
  • @VladD, можно, но сделал специально Array, т.к. будут эффективнее работать First()/Last() – Андрей NOP Feb 01 '18 at 03:07
  • Ах, ну да, нужно материализовать внутреннюю часть. https://ideone.com/5kJaz7 – VladD Feb 01 '18 at 09:41
  • @VladD, можно, да. Если бы был гольф - можно было бы выиграть один символ. А так, я думаю, что Array.ConvertAll должен быть эффективнее ToList/ToArray, т.к. заранее известна длина массива, а после Select уже нет. – Андрей NOP Feb 01 '18 at 09:49
1

На Javascript'е вот так, чуть позже перепишу на linq:

var data = ["17-24 36-41 53-58 138-143 155",
"13-16 32 49-52 66-69",
"13-16 32-35 49-52 66 83 100-103"]

function range(l, r) { var res = []; for (; l<=r; ++l) res.push(l) return res; }

function flatten(arr) { return [].concat(...arr) }

var res = data.map(s => flatten(s.split(" ").map(s => s==+s ? +s : (s=s.split("-"), range(+s[0], +s[1])))))

console.log(res)

.as-console-wrapper.as-console-wrapper { max-height: 100vh }

А вот и версия на C#: https://ideone.com/gMSZKz

using System;
using System.Linq;

public class Test
{
  public static void Main()
  {
    var data = new string []
    {
      "17-24 36-41 53-58 138-143 155",
      "13-16 32 49-52 66-69",
      "13-16 32-35 49-52 66 83 100-103"
    };

    int[][] res = data.Select(line => line.Split().SelectMany(s => {
      int x;

      if (int.TryParse(s, out x))
        return Enumerable.Repeat(x, 1);

      var lr = s.Split('-');
      int l = int.Parse(lr[0]), r = int.Parse(lr[1]);
      return Enumerable.Range(l, r-l+1);
    }).ToArray()).ToArray();

    foreach (var line in res)
      Console.WriteLine("{0}\n===", String.Join(" ", line));
  }
}
Qwertiy
  • 123,725
1
var data = new[] 
{
    "17-24 36-41 53-58 138-143 155",
    "13-16 32 49-52 66-69",
    "13-16 32-35 49-52 66 83 100-103",
};

foreach(var row in data.Split().ParseRange())
    Console.WriteLine(string.Join(" ", row));

Чтобы заработало добавляем методы расширения

public static class ArrayEntentions
{
    public static IEnumerable<IEnumerable<string>> Split(this IEnumerable<string> source, char separator = ' ')
    {
        return source.Select(x => x.Split(separator));
    }

    public static IEnumerable<IEnumerable<int>> ParseRange(this IEnumerable<IEnumerable<string>> source)
    {
        return source.Select(ArrayEntentions.Parse);
    }

    public static IEnumerable<int> Parse(this IEnumerable<string> source)
    {
        foreach(var s in source)
        {
            int o;
            if (int.TryParse(s, out o))
            {
                yield return o;
            }
            else 
            {
                var interval = s.SplitInterval();

                foreach(var i in Enumerable.Range(interval.Item1, interval.Item2))
                    yield return i;
            }
        }
    }

    public static Tuple<int, int> SplitInterval(this string source, char separator = '-')
    {
        var cells = source.Split(separator);
        if (cells.Length != 2) throw new FormatException();

        var start = int.Parse(cells[0]);
        var count = int.Parse(cells[1]) - start + 1;

        return Tuple.Create(start, count);
    }
}
pavelip
  • 5,670