0

int特定の「パターン」に対応するかどうかを判断する方法。「パターン」は、int または int の範囲で構成できます。

メソッドのシグネチャは次のとおりです。

    //Eg of pattern 
    // 10,12,14,16
    // [10-20];21;23
    public bool IsInPattern(int inputToTest, string pattern)
    {
        //Todo
    }

以下のパターンは、';' で区切られた内部パターンのリストを持つ文字列として定義されています。内部パターンは int または範囲 [lowerBound-upperBound] のいずれかです。

正規表現で到達できると信じていますが、成功しませんでした。また、私はなどよりもエレガントなソリューションを好みif subPattern.StartWith('[') then lowerBound = subPattern.Substringます...

4

6 に答える 6

2

パターンを持つのではなく、2 つのメソッドとしてこれを記述します。

public bool IsInSequence(int inputToTest, IEnumerable<int> sequence)
{
    return sequence.Contains(inputToTest);
}

public bool IsInRange(int inputToTest, int start, int end)
{
    return inputToTest>= start && inputToTest<=end ;
}
于 2013-10-28T09:31:30.713 に答える
1

このような単純な解析を使用できます。

public bool IsInPattern(int inputToTest, string pattern)
{
    var numbers = new List<int>();
    var tokens = pattern.Split(new []{",", " ", "or"}, 
                               StringSplitOptions.RemoveEmptyEntries);
    bool to_flag = false;
    foreach(var t in tokens)
    {
        int n;
        if (Int32.TryParse(t, out n))
        {
            if (to_flag) 
                numbers.AddRange(Enumerable.Range(numbers.Last() + 1, 
                                                  n - numbers.Last()));
            else 
                numbers.Add(n);

            to_flag = false;
        }
        else if (t == "to") to_flag = true;
        else throw new Exception("invalid pattern");
    }
    return numbers.Contains(inputToTest);
}

そしてテスト:

IsInPattern(11, "10,12,14,16"); // false
IsInPattern(12, "10,12,14,16"); // true
IsInPattern(11, "10 to 20 or 21 or 23");// true
IsInPattern(22, "10 to 20 or 21 or 23");// false
于 2013-10-28T09:39:05.263 に答える
0

いくつかの値がさまざまな条件を満たすかどうかを確認する必要がある場合は、仕様パターンを使用するのが好きです。仕様は次のようになります。

public interface ISpecification<T>
{
    bool IsSatisfiedBy(T value);
}

条件のセットごとに、異なる仕様クラスを作成します。ここでは、範囲指定が必要になります (int簡単にするためにジェネリック型として使用します)。

public class RangeSpecification : ISpecification<int>
{
    private readonly int _from;
    private readonly int _to;

    public RangeSpecification(int from, int to)
    {
        _to = to;
        _from = from;
    }

    public bool IsSatisfiedBy(int value)
    {
        return _from <= value && value <= _to;
    }
}

値のリストの仕様 (単一の値をリストの仕様と見なすこともできます):

public class InSpecification : ISpecification<int>
{
    private readonly int[] _values;

    public InSpecification(params int[] values)
    {
        _values = values;
    }

    public bool IsSatisfiedBy(int value)
    {
        return _values.Contains(value);
    }
}

次のような条件をテストするには、これで十分です。

var rangeSpec = new RangeSpecification(10, 15);
var is13inRange = rangeSpec.IsSatisfiedBy(13); // true
var is20inRange = rangeSpec.IsSatisfiedBy(20); // false
var inSpec = new InSpecification(1,2,5,8);
var is13inList = inSpec.IsSatisfiedBy(13); // false

しかし、より興味深い条件を構築するには、条件付きロジックを実装する必要があります。

public class OrSpecification<T> : ISpecification<T>
{
    private readonly ISpecification<T> _left;
    private readonly ISpecification<T> _right;

    public OrSpecification(ISpecification<T> left, ISpecification<T> right)
    {
        _right = right;
        _left = left;
    }

    public bool IsSatisfiedBy(T value)
    {
        return _left.IsSatisfiedBy(value) || _right.IsSatisfiedBy(value);
    }
} 

この仕様は、OR 条件を構築して、値が指定された仕様を満たすかどうかを確認するのに役立ちます。また、拡張メソッドを使用して仕様を構築します。

public static class SpecificationExtensions
{
    public static ISpecification<T> Or<T>(
        this ISpecification<T> left, ISpecification<T> right)
    {
        return new OrSpecification<T>(left, right);
    }
}

これで、次のようなものを構築できます。

var spec = new RangeSpecification(10, 15).Or(new InSpecification(1,2,5,8));
var result = spec.IsSatisfiedBy(8); // true

今必要なのは、文字列から仕様を解析することだけです。

public class SpecificationParser
{
    public static ISpecification<int> Parse(string input)
    {
        var parts = input.Split(';');
        return parts.Aggregate(ParseSpec(parts[0]), 
                               (spec, s) => spec.Or(ParseSpec(s)));
    }

    private static ISpecification<int> ParseSpec(string s)
    {
        var match = Regex.Match(s, @"\[(\d+)-(\d+)\]");
        if (match.Success)
        {
            int from = Int32.Parse(match.Groups[1].Value);
            int to = Int32.Parse(match.Groups[2].Value);
            return new RangeSpecification(from, to);
        }

        return new InSpecification(s.Split(',').Select(Int32.Parse).ToArray());
    }
}

それでおしまい。これで、文字列から仕様を解析し、値がそれを満たしているかどうかを確認できます:

var spec1 = SpecificationParser.Parse("10, 12, 14, 16");
spec1.IsSatisfiedBy(11); // false

var spec2 = SpecificationParser.Parse("[10-20];21;23,25");
spec2.IsSatisfiedBy(9); // false
spec2.IsSatisfiedBy(19); // true
spec2.IsSatisfiedBy(22); // false
于 2013-10-28T10:50:24.743 に答える
0

次のようなものかもしれません:

pattern.Split(',').Where(sub=>sub == inputToTest.ToString())

この方法は、範囲がある場合、または定義済みのセパレーターで区切られた任意の整数のシーケンスがある場合に完全に機能します(この具体的なケースでは)

于 2013-10-28T09:27:21.877 に答える
0

次のようなことを試すことができます(これは頭からのものなので、変更なしでは機能しない可能性があります):

public bool IsInPattern(int inputToTest, string pattern)
{
    if (pattern.Contains(","))
        return pattern.Split(',').Contains(inputToTest.ToString());
    else
    {
        var temp = pattern.Split(';');
        if (temp.Contains(inputToTest.ToString()))
            return true;
        else
        {
            temp = temp.RemoveAll(x => !x.Contains("-"));
            foreach (var x in temp)
            {
                string[] a = x.Split("-").Select(x => x.Trim('[',']')).ToArray();
                if (IsInRange(inputToTest, int.Parse(a[0]), int.Parse(a[1])))
                    return true;
            }
        }
    }
    return false;
}

public bool IsInRange(int inputToTest, int start, int end)
{
    return inputToTest >= start && inputToTest <=end;
}
于 2013-10-28T09:41:40.983 に答える