C# имеет встроенную поддержку парсинга строк номера страницы?

Обычно, когда вы выполняете отношения типа Super-type / Sub-type в своем проекте базы данных, вам нужно создать отдельную таблицу для вашего типа общего типа (супертип) и отдельных таблиц для вашей специализированной версии / s (Sub -Type) несвязанный или нет. В вашем случае вам нужно будет создать таблицу для VEHICLE и первичного ключа и некоторых атрибутов, которые являются общими или разделяются всеми подтипами. Затем вам нужно будет создать отдельные таблицы для 2WD и 4WD вместе с атрибутами, специфичными только для этих таблиц. Например,

[/g0]

, тогда вы можете запросить эти таблицы с помощью SQL-соединений

19
задан Enamul Hassan 24 July 2015 в 16:28
поделиться

5 ответов

Должно быть простым:

foreach( string s in "1,3,5-10,12".Split(',') ) 
{
    // try and get the number
    int num;
    if( int.TryParse( s, out num ) )
    {
        yield return num;
        continue; // skip the rest
    }

    // otherwise we might have a range
    // split on the range delimiter
    string[] subs = s.Split('-');
    int start, end;

    // now see if we can parse a start and end
    if( subs.Length > 1 &&
        int.TryParse(subs[0], out start) &&
        int.TryParse(subs[1], out end) &&
        end >= start )
    {
        // create a range between the two values
        int rangeLength = end - start + 1;
        foreach(int i in Enumerable.Range(start, rangeLength))
        {
            yield return i;
        }
    }
}

Редактирование: спасибо за фиксацию ;-)

22
ответ дан 30 November 2019 в 03:08
поделиться

Это не имеет встроенного способа сделать это, но это было бы тривиально, чтобы сделать Строку использования. Разделение.

Просто разделенный на'', затем у Вас есть серия строк, которые представляют или номера страниц или диапазоны. Выполните итерации по тому ряду и сделайте Строку. Разделение '-'. Если нет результата, это - простой номер страницы, так засуньте его в свой список страниц. Если существует результат, возьмите левый и правый из '-' как границы и используйте простое, чтобы цикл добавил каждый номер страницы к Вашему заключительному списку по тому диапазону.

не Может взять только 5 минут, чтобы сделать, затем возможно, еще 10 для добавления в некоторых проверках работоспособности для броска ошибок, когда пользователь пытается ввести недопустимые данные (как "1-2-3" или что-то.)

8
ответ дан 30 November 2019 в 03:08
поделиться

Вот что-то, что я приготовил для чего-то подобного.

Это обрабатывает следующие типы диапазонов:

1        single number
1-5      range
-5       range from (firstpage) up to 5
5-       range from 5 up to (lastpage)
..       can use .. instead of -
;,       can use both semicolon, comma, and space, as separators

Это не проверяет на дублирующиеся значения, таким образом, набор 1,5,-10 произведет последовательность 1, 5, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 .

public class RangeParser
{
    public static IEnumerable<Int32> Parse(String s, Int32 firstPage, Int32 lastPage)
    {
        String[] parts = s.Split(' ', ';', ',');
        Regex reRange = new Regex(@"^\s*((?<from>\d+)|(?<from>\d+)(?<sep>(-|\.\.))(?<to>\d+)|(?<sep>(-|\.\.))(?<to>\d+)|(?<from>\d+)(?<sep>(-|\.\.)))\s*$");
        foreach (String part in parts)
        {
            Match maRange = reRange.Match(part);
            if (maRange.Success)
            {
                Group gFrom = maRange.Groups["from"];
                Group gTo = maRange.Groups["to"];
                Group gSep = maRange.Groups["sep"];

                if (gSep.Success)
                {
                    Int32 from = firstPage;
                    Int32 to = lastPage;
                    if (gFrom.Success)
                        from = Int32.Parse(gFrom.Value);
                    if (gTo.Success)
                        to = Int32.Parse(gTo.Value);
                    for (Int32 page = from; page <= to; page++)
                        yield return page;
                }
                else
                    yield return Int32.Parse(gFrom.Value);
            }
        }
    }
}
2
ответ дан 30 November 2019 в 03:08
поделиться

Подход Keith кажется хорошим. Я соединил более наивный подход с помощью списков. Это имеет проверку ошибок, так, надо надеяться, должен взять большую часть problems:-

public List<int> parsePageNumbers(string input) {
  if (string.IsNullOrEmpty(input))
    throw new InvalidOperationException("Input string is empty.");

  var pageNos = input.Split(',');

  var ret = new List<int>();
  foreach(string pageString in pageNos) {
    if (pageString.Contains("-")) {
      parsePageRange(ret, pageString);
    } else {
      ret.Add(parsePageNumber(pageString));
    }
  }

  ret.Sort();
  return ret.Distinct().ToList();
}

private int parsePageNumber(string pageString) {
  int ret;

  if (!int.TryParse(pageString, out ret)) {
    throw new InvalidOperationException(
      string.Format("Page number '{0}' is not valid.", pageString));
  }

  return ret;
}

private void parsePageRange(List<int> pageNumbers, string pageNo) {
  var pageRange = pageNo.Split('-');

  if (pageRange.Length != 2)
    throw new InvalidOperationException(
      string.Format("Page range '{0}' is not valid.", pageNo));

  int startPage = parsePageNumber(pageRange[0]),
    endPage = parsePageNumber(pageRange[1]);

  if (startPage > endPage) {
    throw new InvalidOperationException(
      string.Format("Page number {0} is greater than page number {1}" +
      " in page range '{2}'", startPage, endPage, pageNo));
  }

  pageNumbers.AddRange(Enumerable.Range(startPage, endPage - startPage + 1));
}
5
ответ дан 30 November 2019 в 03:08
поделиться

Вот немного измененная версия кода lassevk, который обрабатывает строку. Операция разделения в соответствии Regex. Это записано как дополнительный метод, и можно легко решить проблему дубликатов с помощью Disinct () расширение от LINQ.

    /// <summary>
    /// Parses a string representing a range of values into a sequence of integers.
    /// </summary>
    /// <param name="s">String to parse</param>
    /// <param name="minValue">Minimum value for open range specifier</param>
    /// <param name="maxValue">Maximum value for open range specifier</param>
    /// <returns>An enumerable sequence of integers</returns>
    /// <remarks>
    /// The range is specified as a string in the following forms or combination thereof:
    /// 5           single value
    /// 1,2,3,4,5   sequence of values
    /// 1-5         closed range
    /// -5          open range (converted to a sequence from minValue to 5)
    /// 1-          open range (converted to a sequence from 1 to maxValue)
    /// 
    /// The value delimiter can be either ',' or ';' and the range separator can be
    /// either '-' or ':'. Whitespace is permitted at any point in the input.
    /// 
    /// Any elements of the sequence that contain non-digit, non-whitespace, or non-separator
    /// characters or that are empty are ignored and not returned in the output sequence.
    /// </remarks>
    public static IEnumerable<int> ParseRange2(this string s, int minValue, int maxValue) {
        const string pattern = @"(?:^|(?<=[,;]))                      # match must begin with start of string or delim, where delim is , or ;
                                 \s*(                                 # leading whitespace
                                 (?<from>\d*)\s*(?:-|:)\s*(?<to>\d+)  # capture 'from <sep> to' or '<sep> to', where <sep> is - or :
                                 |                                    # or
                                 (?<from>\d+)\s*(?:-|:)\s*(?<to>\d*)  # capture 'from <sep> to' or 'from <sep>', where <sep> is - or :
                                 |                                    # or
                                 (?<num>\d+)                          # capture lone number
                                 )\s*                                 # trailing whitespace
                                 (?:(?=[,;\b])|$)                     # match must end with end of string or delim, where delim is , or ;";

        Regex regx = new Regex(pattern, RegexOptions.IgnorePatternWhitespace | RegexOptions.Compiled);

        foreach (Match m in regx.Matches(s)) {
            Group gpNum = m.Groups["num"];
            if (gpNum.Success) {
                yield return int.Parse(gpNum.Value);

            } else {
                Group gpFrom = m.Groups["from"];
                Group gpTo = m.Groups["to"];
                if (gpFrom.Success || gpTo.Success) {
                    int from = (gpFrom.Success && gpFrom.Value.Length > 0 ? int.Parse(gpFrom.Value) : minValue);
                    int to = (gpTo.Success && gpTo.Value.Length > 0 ? int.Parse(gpTo.Value) : maxValue);

                    for (int i = from; i <= to; i++) {
                        yield return i;
                    }
                }
            }
        }
    }
0
ответ дан 30 November 2019 в 03:08
поделиться
Другие вопросы по тегам:

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