Как проверить, содержит ли список целые целые числа в Mathematica?
Я хочу проверить, содержит ли список последовательные целые числа.
consQ[a_] := Module[
{ret = True},
Do[If[i > 1 && a[[i]] != a[[i - 1]] + 1, ret = False; Break[]], {i,
1, Length[a]}]; ret]
Хотя функция consQ выполняет задание, мне интересно, есть ли лучший (более короткий, быстрый) способ сделать это, предпочтительно используя стиль функционального программирования.
EDIT:
Функция выше отображает списки с последовательными целыми числами в порядке убывания до False. Я хотел бы изменить это на True.
Ответы
Ответ 1
Вы можете использовать
consQ[a_List ? (VectorQ[#, IntegerQ]&)] := [email protected][a] === {1}
consQ[_] = False
Вы можете удалить тест для целых чисел, если знаете, что каждый список, который вы передаете ему, будет иметь целые числа.
EDIT: Немного больше: если вы используете очень старую версию, которая не имеет Differences
, или задаться вопросом, как ее реализовать,
differences[a_List] := Rest[a] - Most[a]
ИЗМЕНИТЬ 2: Запрошенное изменение:
consQ[a : {Integer___}] := MatchQ[[email protected][a], {1} | {-1} | {}]
consQ[_] = False
Это работает как с увеличением, так и с уменьшением последовательностей и дает True
для списка размером 1 или 0.
В более общем смысле, вы можете проверить, равно ли распределен ли список чисел с чем-то вроде equallySpacedQ[a_List] := [email protected]@Differences[a] == 1
Ответ 2
Решение Szablics - это, наверное, то, что я сделал бы, но здесь альтернатива:
consQ[a : {___Integer}] := Most[a] + 1 === Rest[a]
consQ[_] := False
Обратите внимание, что эти подходы отличаются тем, как они обрабатывают пустой список.
Ответ 3
Мне нравятся решения двух других, но меня беспокоят очень длинные списки. Рассмотрим данные
d:dat[n_Integer?Positive]:= d = {1}~Join~Range[1, n]
который имеет свою непоследовательную точку в самом начале. Установив consQ1
для Бретта и consQ2
для Sabololcs, я получаю
AbsoluteTiming[ #[dat[ 10000 ] ]& /@ {consQ1, consQ2}
{ {0.000110, False}, {0.001091, False} }
Или, примерно в десять раз разница между ними, которая остается относительно согласной с несколькими испытаниями. Это время можно сократить примерно наполовину за счет короткого замыкания процесса, используя NestWhile
:
Clear[consQ3]
consQ3[a : {__Integer}] :=
Module[{l = Length[a], i = 1},
NestWhile[# + 1 &, i,
(#2 <= l) && a[[#1]] + 1 == a[[#2]] &,
2] > l
]
который проверяет каждую пару и продолжается, только если они возвращают true. Тайминги
AbsoluteTiming[consQ3[dat[ 10000 ]]]
{0.000059, False}
с
{0.000076, False}
для consQ
. Итак, ответ Бретта довольно близок, но иногда это займет вдвое больше.
Изменить. Я переместил графики данных синхронизации в ответ Community Wiki.
Ответ 4
Я думаю, что следующее также быстро, и сравнение обратных списков не займет больше времени:
a = Range[10^7];
f[a_] := Range[Sequence @@ ##, Sign[-#[[1]] + #[[2]]]] &@{a[[1]], a[[-1]]} == a;
Timing[f[a]]
b = [email protected];
Timing[f[b]]
Edit
Короткий тест для решений по быстродействию:
a = Range[2 10^7];
[email protected]@a
[email protected]@a
[email protected]@a
(*
{6.5,True}
{0.703,True}
{0.203,True}
*)
Ответ 5
Fold
может использоваться в довольно сжатом выражении, которое выполняется очень быстро:
consQFold[a_] := (Fold[If[#2 == #1 + 1, #2, Return[False]] &, a[[1]]-1, a]; True)
Сравнение шаблонов может использоваться для обеспечения очень четкого выражения намерения за счет значительно более низкой производительности:
consQMatch[{___, i_, j_, ___}] /; j - i != 1 := False
consQMatch[_] = True;
Edit
consQFold
, как написано, работает в Mathematica v8.0.4, но не в более ранних версиях v8 или v7. Чтобы исправить эту проблему, существует несколько альтернатив. Первый - явно указать точку Return
:
consQFold[a_] :=
(Fold[If[#2==#1+1, #2, Return[False,CompoundExpression]] &, a[[1]]-1, a]; True)
Второй, как предложил @Mr.Wizard, заключается в замене Return
на Throw
/Catch
:
consQFold[a_] :=
Catch[Fold[If[#2 == #1 + 1, #2, Throw[False]]&, a[[1]]-1, a]; True]
Ответ 6
Теперь я убежден, что belisarius пытается получить мою козу, написав намеренно свернутый код.:-p
Я бы написал: f = Range[##, Sign[#2 - #]]& @@ #[[{1, -1}]] == # &
Кроме того, я считаю, что WReach, вероятно, намеревался написать что-то вроде:
consQFold[a_] :=
Catch[
Fold[If[#2 === # + 1, #2, [email protected]] &, a[[1]] - 1, a];
True
]
Ответ 7
Поскольку время кажется весьма важным. Я переместил сравнения между различными методами на это, Community Wiki, ответ.
Используемые данные - это просто списки последовательных целых чисел с одной непоследовательной точкой, и они генерируются через
d : dat[n_Integer?Positive] := (d = {1}~Join~Range[1, n])
d : dat[n_Integer?Positive, p_Integer?Positive] /; p <= n :=
Range[1, p]~Join~{p}~Join~Range[p + 1, n]
где первая форма dat[n]
эквивалентна dat[n, 1]
. Код синхронизации прост:
Clear[consQTiming]
Options[consQTiming] = {
NonConsecutivePoints -> {10, 25, 50, 100, 250,500, 1000}};
consQTiming[fcns__, OptionPattern[]]:=
With[{rnd = RandomInteger[{1, #}, 100]},
With[{fcn = #},
Timing[ fcn[dat[10000, #]] & /@ rnd ][[1]]/100
] & /@ {fcns}
] & /@ OptionValue[NonConsecutivePoints]
Он генерирует 100 случайных чисел от 1 до каждого из {10, 25, 50, 100, 250, 500, 1000}
и dat
, а затем использует каждое из этих случайных чисел в качестве непоследовательной точки в списке 10000 элементов. Каждая реализация consQ
затем применяется к каждому списку, создаваемому dat
, и результаты усредняются. Функция построения графика просто
Clear[PlotConsQTimings]
Options[PlotConsQTimings] = {
NonConsecutivePoints -> {10, 25, 50, 100, 250, 500, 1000}};
PlotConsQTimings[timings : { _?VectorQ ..}, OptionPattern[]] :=
ListLogLogPlot[
Thread[{OptionValue[NonConsecutivePoints], #}] & /@ Transpose[timings],
Frame -> True, Joined -> True, PlotMarkers -> Automatic
]
![timing data for various functions]()
Я приурочил следующие функции consQSzabolcs1
, consQSzabolcs2
, consQBrett
, consQRCollyer
, consQBelisarius
, consQWRFold
, consQWRFold2
, consQWRFold3
, consQWRMatch
и версия MrWizard consQBelisarius
.
В порядке возрастания самого последнего времени: consQBelisarius
, consQWizard
, consQRCollyer
, consQBrett
, consQSzabolcs1
, consQWRMatch
, consQSzabolcs2
, consQWRFold2
, consQWRFold3
и consQWRFold
.
Изменить. Повторите все функции с timeAvg
(второй) вместо Timing
в consQTiming
. Тем не менее, я все же выполнял более 100 пробегов. По большей части произошли какие-либо изменения, за исключением самых низких двух, где есть несколько вариантов от запуска до запуска. Итак, возьмите эти две линии с зерном соли, поскольку они тайминги практически идентичны.
![enter image description here]()