Показать полную графическую версию : [решено] Условие - любые два из всех
DJ Mogarych
19-01-2022, 09:28
Привет!
Подскажите, пожалуйста, что-то я торможу. Есть несколько переменных.
Понадобилось написать условие, в котором любые две переменные из набора должны быть равны 2, иначе тревога.
Можно, конечно, и так написать:
$1 = 4
$2 = 4
$3 = 2
if (($1 -ne 2 -and $2 -ne 2) -or ($2 -ne 2 -and $3 -ne 2) -or ($1 -ne 2 -and $3 -ne 2)) {
"Тревога!"
}
else {
"ОК"
}
Но это по-уродски, тем более, что будет, если переменных будет 100?
Как грамотно написать условие?
Массив, после его сортировка, после сравнение двух соседних элементов, если они равны, то прерывание и выход с "OK", при достижении конца массива выход с "Тревога!".
UPD:
А Вам же только ДВОЙКИ считать? Тогда количество двоек в массиве и подсчитать.
Читая тему "PowerShell - Условие - любые два из всех" подумалось, что любые две переменные имели бы одинаковые значения.
DJ Mogarych
19-01-2022, 10:11
любые две переменные имели бы одинаковые значения »
Ну да. В данном случае двойки, но в целом может быть что угодно.
Я вообще про Zabbix спрашиваю, как там теперь реализовать.
Офф-топ кончено, но на Паскале (https://www.onlinegdb.com/online_pascal_compiler) это могло бы выглядеть, например, так:
const n=15;
var
v:array[1..n] of real;
k:integer;
procedure qSort(l,r:integer);
var i,j:integer;
w,q:real;
begin
i := l; j := r;
q := v[(l+r) div 2];
repeat
while (v[i] < q) do inc(i);
while (q < v[j]) do dec(j);
if (i <= j) then
begin
w:=v[i]; v[i]:=v[j]; v[j]:=w;
inc(i); dec(j);
end;
until (i > j);
if (l < j) then qSort(l,j);
if (i < r) then qSort(i,r);
end;
begin
randomize;
for k:=1 to n do begin //Получаем массив значений
v[k]:=random(100);
writeln(round(v[k]));
end;
writeln('---');
qSort(1, n); //Сортируем массив
for k:=1 to n do begin
writeln(round(v[k]));
end;
writeln('---');
for k:=1 to n do
if v[k]=v[k+1] then begin //Сравниваем два соседних элемента, при совпадении выходим и сообщаем, что нашли
writeln(round(v[k]), ' , OK!');
break;
end;
if k=n then writeln('Nothing'); //Двух одинаковых не нашли - сообщаем об этом
end.
Осталось только на Powershell переложить :biggrin:
DJ Mogarych
19-01-2022, 11:08
сравнение двух соседних элементов, если они равны, то прерывание и выход с "OK" »
Двух соседних, совпадающих с двойкой, верно?
Да, видать, только поиск в массиве.
$1 = 2
$2 = 4
$3 = 4
if (($1,$2,$3 -eq 2).count -ne 2) {
"Тревога!"
}
else {
"ОК"
}
В Заббиксе тупо решил суммой...
sum(last(/Ramos Ultra/drycontactSensor[4]),last(/Ramos Ultra/drycontactSensor[6]),last(/Ramos Ultra/drycontactSensor[8]))<>8
Двух соседних, совпадающих с двойкой, верно? »
Любых, меньших/ первых (т.к. массив сортируется по возрастанию) совпадающих в массиве.
Выше приведённый пример на Паскале демонстрирует это.
DJ Mogarych
19-01-2022, 13:03
Ну любых не подойдёт же. Если массив, например, 4444444211111, то это не сработает.
Если массив, например, 4444444211111, то это не сработает. »
Т.е. типа такого?
const n=15;
const f=2;
var
v:array[1..n] of real;
k:integer;
procedure qSort(l,r:integer);
var i,j:integer;
w,q:real;
begin
i := l; j := r;
q := v[(l+r) div 2];
repeat
while (v[i] < q) do inc(i);
while (q < v[j]) do dec(j);
if (i <= j) then
begin
w:=v[i]; v[i]:=v[j]; v[j]:=w;
inc(i); dec(j);
end;
until (i > j);
if (l < j) then qSort(l,j);
if (i < r) then qSort(i,r);
end;
begin
randomize;
for k:=1 to n do begin //Получаем массив значений
v[k]:=random(10)+1;
writeln(round(v[k]));
end;
writeln('---');
qSort(1, n); //Сортируем массив
for k:=1 to n do begin
writeln(round(v[k]));
end;
writeln('---');
for k:=1 to n do
if (v[k]=f) and (v[k]=v[k+1]) then begin //Сравниваем два соседних элемента, при совпадении выходим и сообщаем, что нашли
writeln(round(v[k]), ', Ok, found!');
break;
end;
if k=n then writeln('Nothing found.'); //Двух одинаковых не нашли - сообщаем об этом
end.
Некоторые результаты:
---
1
1
1
2
2
3
3
3
5
7
8
9
10
10
10
---
2, Ok, found!
---
1
3
3
4
5
5
6
8
8
8
8
9
9
10
10
---
Nothing found.
---
1
1
1
2
3
4
5
6
6
6
6
7
8
9
9
---
Nothing found.
Можно использовать делегата сортировки массива (List), но там сравнение может быть не по порядку, в зависимости от алгоритма сортировки.
$1 = 4
$2 = 4
$3 = 2
[Comparison[object]]$func = {
param($i, $j)
if ($i -eq $j) { return }
$v1 = gv $i -ValueOnly; $v2 = gv $j -ValueOnly
if ($v1 -ne 2 -and $v2 -ne 2) {
Write-Host "`$$i = $v1; `$$j = $v2";
throw 'тревога'
}
}
$list = [Collections.Generic.List[object]](
get-variable | where Name -match '\d+').Name
if ($list.Length) {
try { $list.Sort($func); 'OK' }
catch { $Error[1].FullyQualifiedErrorId }
}
DJ Mogarych
19-01-2022, 15:17
Я так понимаю, что эффективнее всего выцеплять из массива нужные значения и потом подсчитывать их количество. Или нет?
megaloman
19-01-2022, 15:54
DJ Mogarych, Ни разу не писал здесь посты в PowerShell - далёк от него. любые две переменные из набора должны быть равны 2Не обижайте ребёнка за наивность:$1 = 222
$2 = 2
$3 = 2
if (($1 -eq 2) + ($2 -eq 2) + ($3 -eq 2) -ge 2) {"OK"} else {"Тревога"}Или$1 = 4
$2 = 7
$3 = 2
$Alarm=($1 -eq 2) + ($2 -eq 2) + ($3 -eq 2)
if ($Alarm -ge 2) {"OK"} else {"Тревога"}Наверное для массива можно поступить так же, но в цикле.
судя по условию, если любые две переменные не равны двум, то "тревога". Для тревоги находим первую пару переменных, которые все не 2. Непонятно, для чего нужен полный перебор пар переменных, и нужен ли. Если хотя бы две из набора не равны 2, то при полном переборе они встретятся.
DJ Mogarych
19-01-2022, 17:35
megaloman, интересный подход, спасибо.
Sham, условие такое - из всех переменных две обязательно должны быть равны 2, иначе тревога.
Непонятно»
Вот!
Непонятно было по первому посту.
условие такое - из всех переменных две обязательно должны быть равны 2, иначе тревога. »
Разве так?
Вы выше говорили, что не только равны между собою, но и ещё конкретному значению?!
2 Вы приводили лишь только в качестве конкретного примера, не так ли?
DJ Mogarych
19-01-2022, 17:51
2 Вы приводили лишь только в качестве конкретного примера, не так ли? »
Да.В данном случае двойки, но в целом может быть что угодно. »
Давайте так: из всех переменных две обязательно должны быть равны X, иначе тревога.
тогда можно и так, наверное (get-variable | where {$_.Name -match '^\d+$' -and $_.Value -eq 2}).Length
что эффективнее всего выцеплять из массива нужные значения и потом подсчитывать их количество »
Получается что так - можно обойтись одним циклом, причём от условий/ порядка переменных ещё и не полным перебором массива.
UPD: Как Мне кажется, предварительной сортировкой массива удобней пользоваться, т.к., зачастую, уже имеется готовый функционал, полагаю и в powershell тоже. Ну, а на выходе Мы уже имеем "подготовленный" массив, в котором уже достаточно сравнить только два соседних элемента - (i) и (i+1).
две обязательно должны быть равны X »
разве это не самый обычный поиск дубликата?
$a = 1
$b = 2
$c = 3
$d = 2
$e = 5
$arr = @($a, $b, $c, $d, $e)
$alarm = $arr|group|where {$_.Count -gt 1}
if ($alarm) {'Alarm!'}
и да, если еще и задан дубль, то поиск будет еще быстрее:
$a = 22
$b = 2
$c = 3
$d = 2
$e = 5
$arr = @($a, $b, $c, $d, $e)
$alarm = $arr -Match '^2$'|group
if ($alarm.Count -gt 1) {'Alarm!'}
Давайте так: из всех переменных две обязательно должны быть равны X, иначе тревога. »
для быстрого подсчета:
$1,$2,$3,$4,$5,$n = 4,4,2,6,7,8
[int[]]$arr = $1,$2,$3,$4,$5,$n
$X = 2
if([linq.enumerable]::count($arr, [Func[int,bool]]{$args[0] -eq $X }) -lt 2){"Алярм"} else {"Норма"}
ЗЫ Условие надо бы уточнить: только две, или не меньше двух?
megaloman
20-01-2022, 19:18
$1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11 = 1, 32, 3.141526, 4, 5, 2, 754, 3.141526, 2, 398, 222
$x, $nx = 3.141526, 2
$Alarm = 0
($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11).ForEach({ $Alarm += $_ -eq $x })
if ($Alarm -ge $nx) {"OK"} else {"Тревога"}$1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11 = 1, 32, 3.1415264, 4, 5, 2, 754, 3.141526, 2, 398, 222
$x, $nx = 3.141526, 2
$Alarm = (($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11).Where{ $_ -eq $x }).count -ge $nx
if ($Alarm) {"OK"} else {"Тревога"}
© OSzone.net 2001-2012
vBulletin v3.6.4, Copyright ©2000-2025, Jelsoft Enterprises Ltd.