переключить стиль C # конструкция с двойными диапазонами - PullRequest
3 голосов
/ 01 марта 2012

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

double a = 1.1;
switch(a)
{
case: (0.0, 1.6)
 return 1;
case: (1.6, 2.337)
 return 2;
case: (2.337, 3.2974)
 return 3;
default:
  return -1;
}

Очевидно, в этомНапример, одно значение в диапазоне должно быть не включительно, но вы меня поняли.Любые идеи?

Править, диапазоны не обязательно являются целочисленными.

РЕДАКТИРОВАТЬ 2: Я на самом деле имею дело с радианами и выясняю, в каком из 12 диапазонов находится точка.this:

double pi = Math.PI;
double[] zones = new double[] {
        0, pi/6, pi/3, pi/2,
        2*pi/3, 5*pi/6, pi, 7*pi/6,
        4*pi/3, 3*pi/2, 5*pi/3, 11*pi/6
    };

for (int i = 0; i < 11; i++)
{
    if (radians > zones[i] && radians <= zones[i + 1])
    {
        return i + 1;
    }
}

Я начал делать бинарный тип поиска if-else, но он собирался запутаться.

Ответы [ 5 ]

7 голосов
/ 01 марта 2012

Следующее идеально подходит для соседних диапазонов, так как вам нужно записать пределы диапазона только один раз:

double a = 1.1;

if (a < 0.0) {
    // Too low
    return -1;
} else if (a < 1.6) {
    // Range [0.0, 1.6)
    return 1;
} else if (a < 2.337) {
    // Range [1.6, 2.337)
    return 2;
} else if (a < 3.2974) {
    // Range [2.337, 3.2974)
    return 3;
} else {
    // Too high
    return -1;
}
3 голосов
/ 01 марта 2012

Вероятно, это больше, чем проектирование, но вы можете создать класс Range со значениями Min и Max и функцией обратного вызова.

Затем просто создайте все диапазоны с соответствующими минимальными и максимальными значениями и обратным вызовом и добавьте их в IEnumerable.

Используйте LINQ, чтобы узнать правильный диапазон:

range = Ranges.First(r => r.MinValue <= value and r.MaxValue > value);

Тогда просто вызовите обратный вызов диапазона.

1 голос
/ 01 марта 2012

Просто округлим

double a = 1.1;
if(d < 0.0)
  return -1;
else
  return (int)Math.Ceiling(a);
0 голосов
/ 01 марта 2012

Возможно, это будет делать то, что вы хотите сделать с хорошей синтаксической структурой. Пожалуйста, настройте видимость и сравнение в соответствии с вашими целями:

public static class Range
{
    public interface ISwitchable
    {
        void SetDefault(Action defaultStatement);
        void Execute();
    }

    public interface ISwitchable<T>: ISwitchable
        where T: IComparable<T>
    {
        T Value { get; set; }
        void AddCase(ICase<T> caseStatement);
    }

    public class Switchable<T> : ISwitchable<T>
        where T: IComparable<T>
    {
        private readonly IList<ICase<T>> _caseStatements = new List<ICase<T>>();
        private Action _defaultStatement;

        #region ISwitchable<T> Members

        public T Value { get; set; }

        public void AddCase(ICase<T> caseStatement)
        {
            _caseStatements.Add(caseStatement);
        }

        public void SetDefault(Action defaultStatement)
        {
            _defaultStatement = defaultStatement;
        }

        public void Execute()
        {
            foreach (var caseStatement in _caseStatements)
                if ((caseStatement.Min.CompareTo(Value) <= 0) && (caseStatement.Max.CompareTo(Value) > 0))
                {
                    caseStatement.Action();
                    return;
                }

            _defaultStatement();
        }

        #endregion
    }

    public interface ICase<T>
        where T: IComparable<T>
    {
        T Min { get; set; }
        T Max { get; set; }

        Action Action { get; set; }
    }

    public sealed class Case<T>: ICase<T>
        where T: IComparable<T>
    {
        #region ICase<T> Members

        public T Min { get; set; }

        public T Max { get; set; }

        public Action Action { get; set; }

        #endregion
    }

    public static ISwitchable<T> Switch<T>(T value)
        where T: IComparable<T>
    {
        return new Switchable<T>();
    }
}

public static class SwitchableExtensions
{
    public static Range.ISwitchable<T> Case<T>(this Range.ISwitchable<T> switchable, T min, T max, Action action)
        where T: IComparable<T>
    {
        switchable.AddCase(new Range.Case<T>{ Min = min, Max = max, Action = action });
        return switchable;
    }
    public static void Default(this Range.ISwitchable switchable, Action action)
    {
        switchable.SetDefault(action);
        switchable.Execute();
    }
}

Использование:

class Program
{
    static void Main(string[] args)
    {
        Range.Switch(10)
            .Case(0, 3, () => Console.WriteLine("Between 0 and 3"))
            .Case(3, 7, () => Console.WriteLine("Between 3 and 7"))
            .Default(() => Console.WriteLine("Something else"));
    }
}
0 голосов
/ 01 марта 2012

Вы не можете сделать это с switch.

if(a >= 0 && a < 1) return 1;
else if(a < 2) return 2;

и т.д.

В качестве альтернативы, вы могли бы написать класс для хранения minval, maxval и outputval, а затем просто выполнить итерацию по этим возможностям и вернуть соответствующий выходной значение.

...