Компьютерный форум OSzone.net  

Компьютерный форум OSzone.net (http://forum.oszone.net/index.php)
-   Скриптовые языки администрирования Windows (http://forum.oszone.net/forumdisplay.php?f=102)
-   -   [решено] Условие - любые два из всех (http://forum.oszone.net/showthread.php?t=350515)

DJ Mogarych 19-01-2022 09:28 2978064

Условие - любые два из всех
 
Привет!

Подскажите, пожалуйста, что-то я торможу. Есть несколько переменных.
Понадобилось написать условие, в котором любые две переменные из набора должны быть равны 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?

Как грамотно написать условие?

NickM 19-01-2022 09:51 2978067

Массив, после его сортировка, после сравнение двух соседних элементов, если они равны, то прерывание и выход с "OK", при достижении конца массива выход с "Тревога!".

UPD:
А Вам же только ДВОЙКИ считать? Тогда количество двоек в массиве и подсчитать.
Читая тему "PowerShell - Условие - любые два из всех" подумалось, что любые две переменные имели бы одинаковые значения.

DJ Mogarych 19-01-2022 10:11 2978071

Цитата:

Цитата NickM
любые две переменные имели бы одинаковые значения »

Ну да. В данном случае двойки, но в целом может быть что угодно.

Я вообще про Zabbix спрашиваю, как там теперь реализовать.

NickM 19-01-2022 10:45 2978076

Офф-топ кончено, но на Паскале это могло бы выглядеть, например, так:
Скрытый текст
Код:

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 2978082

Цитата:

Цитата NickM
сравнение двух соседних элементов, если они равны, то прерывание и выход с "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

NickM 19-01-2022 12:05 2978090

Цитата:

Цитата DJ Mogarych
Двух соседних, совпадающих с двойкой, верно? »

Любых, меньших/ первых (т.к. массив сортируется по возрастанию) совпадающих в массиве.
Выше приведённый пример на Паскале демонстрирует это.

DJ Mogarych 19-01-2022 13:03 2978094

Ну любых не подойдёт же. Если массив, например, 4444444211111, то это не сработает.

NickM 19-01-2022 13:25 2978100

Цитата:

Цитата DJ Mogarych
Если массив, например, 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.


Sham 19-01-2022 13:51 2978102

Можно использовать делегата сортировки массива (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 2978112

Я так понимаю, что эффективнее всего выцеплять из массива нужные значения и потом подсчитывать их количество. Или нет?

megaloman 19-01-2022 15:54 2978117

DJ Mogarych, Ни разу не писал здесь посты в PowerShell - далёк от него.
Цитата:

Цитата DJ Mogarych
любые две переменные из набора должны быть равны 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 {"Тревога"}

Наверное для массива можно поступить так же, но в цикле.

Sham 19-01-2022 17:03 2978127

судя по условию, если любые две переменные не равны двум, то "тревога". Для тревоги находим первую пару переменных, которые все не 2. Непонятно, для чего нужен полный перебор пар переменных, и нужен ли. Если хотя бы две из набора не равны 2, то при полном переборе они встретятся.

DJ Mogarych 19-01-2022 17:35 2978132

megaloman, интересный подход, спасибо.

Sham, условие такое - из всех переменных две обязательно должны быть равны 2, иначе тревога.

NickM 19-01-2022 17:49 2978136

Цитата:

Цитата Sham
Непонятно»

Вот!
Непонятно было по первому посту.

Цитата:

Цитата DJ Mogarych
условие такое - из всех переменных две обязательно должны быть равны 2, иначе тревога. »

Разве так?
Вы выше говорили, что не только равны между собою, но и ещё конкретному значению?!
2 Вы приводили лишь только в качестве конкретного примера, не так ли?

DJ Mogarych 19-01-2022 17:51 2978138

Цитата:

Цитата NickM
2 Вы приводили лишь только в качестве конкретного примера, не так ли? »

Да.
Цитата:

Цитата DJ Mogarych
В данном случае двойки, но в целом может быть что угодно. »

Давайте так: из всех переменных две обязательно должны быть равны X, иначе тревога.

Sham 19-01-2022 18:03 2978143

тогда можно и так, наверное
Код:

(get-variable | where {$_.Name -match '^\d+$' -and $_.Value -eq 2}).Length

NickM 19-01-2022 18:54 2978151

Цитата:

Цитата DJ Mogarych
что эффективнее всего выцеплять из массива нужные значения и потом подсчитывать их количество »

Получается что так - можно обойтись одним циклом, причём от условий/ порядка переменных ещё и не полным перебором массива.

UPD: Как Мне кажется, предварительной сортировкой массива удобней пользоваться, т.к., зачастую, уже имеется готовый функционал, полагаю и в powershell тоже. Ну, а на выходе Мы уже имеем "подготовленный" массив, в котором уже достаточно сравнить только два соседних элемента - (i) и (i+1).

alpap 20-01-2022 01:52 2978197

Цитата:

Цитата DJ Mogarych
две обязательно должны быть равны 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!'}


YuS_2 20-01-2022 08:15 2978211

Цитата:

Цитата DJ Mogarych
Давайте так: из всех переменных две обязательно должны быть равны 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 2978306

Код:

$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 {"Тревога"}


DJ Mogarych 20-01-2022 20:02 2978310

Ну да, делать массив, потом считать.
Всем спасибо!


Время: 18:17.

Время: 18:17.
© OSzone.net 2001-