Обычно, когда вы выполняете отношения типа Super-type / Sub-type в своем проекте базы данных, вам нужно создать отдельную таблицу для вашего типа общего типа (супертип) и отдельных таблиц для вашей специализированной версии / s (Sub -Type) несвязанный или нет. В вашем случае вам нужно будет создать таблицу для VEHICLE и первичного ключа и некоторых атрибутов, которые являются общими или разделяются всеми подтипами. Затем вам нужно будет создать отдельные таблицы для 2WD и 4WD вместе с атрибутами, специфичными только для этих таблиц. Например,
[/g0]
, тогда вы можете запросить эти таблицы с помощью SQL-соединений
Должно быть простым:
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;
}
}
}
Редактирование: спасибо за фиксацию ;-)
Это не имеет встроенного способа сделать это, но это было бы тривиально, чтобы сделать Строку использования. Разделение.
Просто разделенный на'', затем у Вас есть серия строк, которые представляют или номера страниц или диапазоны. Выполните итерации по тому ряду и сделайте Строку. Разделение '-'. Если нет результата, это - простой номер страницы, так засуньте его в свой список страниц. Если существует результат, возьмите левый и правый из '-' как границы и используйте простое, чтобы цикл добавил каждый номер страницы к Вашему заключительному списку по тому диапазону.
не Может взять только 5 минут, чтобы сделать, затем возможно, еще 10 для добавления в некоторых проверках работоспособности для броска ошибок, когда пользователь пытается ввести недопустимые данные (как "1-2-3" или что-то.)
Вот что-то, что я приготовил для чего-то подобного.
Это обрабатывает следующие типы диапазонов:
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);
}
}
}
}
Подход 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));
}
Вот немного измененная версия кода 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;
}
}
}
}
}