Мне очень нравится решение, предложенное @Brian Diggs. Однако в моем случае я создаю линейные графики в цикле, а не предоставляю их явно, потому что я не знаю apriori, сколько графиков у меня будет. Когда я попытался адаптировать код @ Брайана, я столкнулся с некоторыми проблемами с правильной обработкой цветов. Оказалось, мне нужно было изменить эстетические функции. Если у кого-то такая же проблема, вот код, который работал для меня.
Я использовал тот же фрейм данных, что и @Brian:
data <- structure(list(month = structure(c(1317452400, 1317538800, 1317625200, 1317711600,
1317798000, 1317884400, 1317970800, 1318057200,
1318143600, 1318230000, 1318316400, 1318402800,
1318489200, 1318575600, 1318662000, 1318748400,
1318834800, 1318921200, 1319007600, 1319094000),
class = c("POSIXct", "POSIXt"), tzone = ""),
TempMax = c(26.58, 27.78, 27.9, 27.44, 30.9, 30.44, 27.57, 25.71,
25.98, 26.84, 33.58, 30.7, 31.3, 27.18, 26.58, 26.18,
25.19, 24.19, 27.65, 23.92),
TempMed = c(22.88, 22.87, 22.41, 21.63, 22.43, 22.29, 21.89, 20.52,
19.71, 20.73, 23.51, 23.13, 22.95, 21.95, 21.91, 20.72,
20.45, 19.42, 19.97, 19.61),
TempMin = c(19.34, 19.14, 18.34, 17.49, 16.75, 16.75, 16.88, 16.82,
14.82, 16.01, 16.88, 17.55, 16.75, 17.22, 19.01, 16.95,
17.55, 15.21, 14.22, 16.42)),
.Names = c("month", "TempMax", "TempMed", "TempMin"),
row.names = c(NA, 20L), class = "data.frame")
В моем случае я генерирую динамические my.cols
и my.names
, но я не хочу делать вещи излишне сложны, поэтому я даю их явно здесь. Эти три строки упрощают упорядочение легенды и присваивают цвета.
my.cols <- heat.colors(3, alpha=1)
my.names <- c("TempMin", "TempMed", "TempMax")
names(my.cols) <- my.names
И вот график:
p <- ggplot(data, aes(x = month))
for (i in 1:3){
p <- p + geom_line(aes_(y = as.name(names(data[i+1])), colour =
colnames(data[i+1])))#as.character(my.names[i])))
}
p + scale_colour_manual("",
breaks = as.character(my.names),
values = my.cols)
p
"делегат + = метод" является оператором для многоадресного делегата для объединения метода для делегирования. В другом ручном "делегате - = метод" является оператором для удаления метода от делегата. Это полезно для Действия.
Action action = Method1;
action += Method2;
action += Method3;
action -= Method2;
action();
В этом случае, только Method1 и Method3 будут работать, Method2 не будет работать, потому что Вы удаляете метод, прежде чем вызовут делегата.
при использовании многоадресного делегата с Func результатом будет последний метод.
Func<int> func = () => 1;
func += () => 2;
func += () => 3;
int result = func();
В этом случае, результат будет 3, начиная с метода" () =>, 3 дюйма являются последним методом, добавленным к делегату. Так или иначе весь метод назовут.
В Вашем случае, метод "t => t. Сумма < 100" будет эффективным.
, Если Вы хотите объединить предикат, я предлагаю эти дополнительные методы.
public static Func<T, bool> AndAlso<T>(
this Func<T, bool> predicate1,
Func<T, bool> predicate2)
{
return arg => predicate1(arg) && predicate2(arg);
}
public static Func<T, bool> OrElse<T>(
this Func<T, bool> predicate1,
Func<T, bool> predicate2)
{
return arg => predicate1(arg) || predicate2(arg);
}
Использование
public static Func<Tran, bool> GetPredicate() {
Func<Tran, bool> predicate = null;
predicate = t => t.Response == "00";
predicate = predicate.AndAlso(t => t.Amount < 100);
return predicate;
}
РЕДАКТИРОВАНИЕ: исправьте название дополнительных методов, как Keith предполагает.
Когда Вы используете + = или - =, когда делегат вводит, который просто звонит к Delegate.Combine
и Delegate.Remove
.
важная вещь о многоадресных делегатах состоит в том, что возвращаемое значение все кроме последнего выполняемого делегата проигнорированы. Они все выполняются (если исключение не выдается), но только последнее возвращаемое значение используется.
Для предикатов, Вы могли бы хотеть сделать что-то как:
public static Func<T, bool> And<T>(params Func<T, bool>[] predicates)
{
return t => predicates.All(predicate => predicate(t));
}
public static Func<T, bool> Or<T>(params Func<T, bool>[] predicates)
{
return t => predicates.Any(predicate => predicate(t));
}
Вы затем сделали бы:
Func<string, bool> predicate = And<string>(
t => t.Length > 10,
t => t.Length < 20);
РЕДАКТИРОВАНИЕ: вот более общее решение, которое довольно забавно, если немного причудливый...
public static Func<TInput, TOuput> Combine<TInput, TOutput>
(Func<TOutput, TOutput, TOutput> aggregator,
params Func<TInput, TOuput>[] delegates) {
// delegates[0] provides the initial value
return t => delegates.Skip(1).Aggregate(delegates[0](t), aggregator);
}
, Таким образом, Вы могли затем реализация И как:
public static Func<T, bool> And<T>(params Func<T, bool>[] predicates) {
return Combine<T, bool>((x, y) => x && y, predicates);
}
(я лично предпочитаю это по использованию GetInvocationList()
, потому что Вы заканчиваете с предикатом, который можно передать другим битам LINQ и т.д.)
На самом деле это не работает. Попытайтесь протестировать его со случаем, где первое условие ПЕРЕСТАЛО РАБОТАТЬ, но вторые передачи. Вы найдете, что это возвратит true. Причина, потому что при контакте с многоадресными делегатами, которые возвращают значения, только последнее значение возвращено. Например:
Func<string, bool> predicate = null;
predicate += t => t.Length > 10;
predicate += t => t.Length < 20;
bool b = predicate("12345");
Это возвратит TRUE, потому что последний вызов функции возвращает true (это - меньше чем 20). Чтобы действительно заставить его работать, необходимо звонить:
predicate.GetInvocationList();
, который возвращает массив делегатов. Затем необходимо удостовериться, что они ВСЕ возвращают true для конечного результата быть верными. Иметь смысл?
Подробно останавливаясь на ответе BFREE (+1'd это)
, Если Вы хотите получить поведение, которое Вы ищете, необходимо будет явно объединить предикаты в цепочку вместе. Вот пример
public static Func<Tran, bool> GetPredicate()
{
Func<Tran, bool> predicate1 = t => t.Response == "00";
Func<Tran, bool> predicate2 = t => t.Amount < 100;
return t => predicate1(t) && predicate2(t);
}
Если Вы хотите объединить предикаты, попробуйте это;
public static Predicate<T> Combine<T>(params Predicate<T>[] predicates)
{
return t => predicates.All(pr => pr(t));
}
Вы называете его как это;
Predicate<string> shortAndSweet = Combine<string>
(
s => s.Length < 10, // short,
s => s == "sweet" // and sweet
);
+ = синтаксический сахар, конкретно реализованный для поддержки добавляющих обработчиков к событиям. Так как события являются просто особым случаем делегата, и Func является также делегатом, синтаксис появляется для работы здесь.
, Но действительно ли Вы уверены, что это работает как ожидалось? Этим я имею в виду, Вы ожидаете И или ИЛИ оценка? Как Вы реализовали бы противоположное, если бы Вы хотели его? Вы уверены, что это только возвращает результат первого? Или последнее?