Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/string/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Wolfram mathematica 如何在Mathematica中测试列表是否包含连续整数?_Wolfram Mathematica - Fatal编程技术网

Wolfram mathematica 如何在Mathematica中测试列表是否包含连续整数?

Wolfram mathematica 如何在Mathematica中测试列表是否包含连续整数?,wolfram-mathematica,Wolfram 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可以完成这项工作,但我想知道是否有更好(更短、更快)的方法来完成这项工作,最好使用函数式编程风格 编辑: 上面的函数将具有递减序列的连续整数的列表映射为Fal

我想测试一个列表是否包含连续整数

 consQ[a_] := Module[
  {ret = True}, 
  Do[If[i > 1 && a[[i]] != a[[i - 1]] + 1, ret = False; Break[]], {i, 
  1, Length[a]}]; ret]
尽管函数consQ可以完成这项工作,但我想知道是否有更好(更短、更快)的方法来完成这项工作,最好使用函数式编程风格

编辑: 上面的函数将具有递减序列的连续整数的列表映射为False。我想将此更改为True。

您可以使用

consQ[a_List ? (VectorQ[#, IntegerQ]&)] := Union@Differences[a] === {1}
consQ[_] = False
如果您知道传递给它的每个列表都只有整数,那么您可能希望删除整数测试

 consQ[a_] := Module[
  {ret = True}, 
  Do[If[i > 1 && a[[i]] != a[[i - 1]] + 1, ret = False; Break[]], {i, 
  1, Length[a]}]; ret]
编辑:多一点:如果您使用的是一个非常旧的版本,没有任何差异,或者不知道如何实现它

differences[a_List] := Rest[a] - Most[a]
编辑2:请求的更改:

consQ[a : {Integer___}] := MatchQ[Union@Differences[a], {1} | {-1} | {}]
consQ[_] = False
这适用于递增和递减序列,并为大小为1或0的列表提供
True


更一般地说,您可以测试数字列表的间距是否相等,例如
equallySpacedQ[a_list]:=Length@Union@差异[a]==1

Szablics的解决方案可能就是我要做的,但这里有一个替代方案:

consQ[a : {___Integer}] := Most[a] + 1 === Rest[a]
consQ[_] := False

请注意,这些方法在处理空列表的方式上有所不同。

我喜欢其他两种方法的解决方案,但我会担心很长的列表。考虑数据

d:dat[n_Integer?Positive]:= d = {1}~Join~Range[1, n]
从一开始就有它的非连续点。设置Brett's的
consQ1
和Szabolcs的
consQ2
,我得到

AbsoluteTiming[ #[dat[ 10000 ] ]& /@ {consQ1, consQ2}
{ {0.000110, False}, {0.001091, False} }
或者,两者相差大约十倍,这与多次试验相对一致。此时间可通过以下方式缩短一半:

对于
consQ
。因此,布雷特的答案相当接近,但有时,它需要两倍的时间


编辑:我将计时数据的图形移动到了a。

折叠
可以在一个相当简洁的表达式中使用,该表达式运行速度非常快:

consQFold[a_] := (Fold[If[#2 == #1 + 1, #2, Return[False]] &, a[[1]]-1, a]; True)
模式匹配可用于提供非常清晰的意图表达,但代价是性能大大降低:

consQMatch[{___, i_, j_, ___}] /; j - i != 1 := False
consQMatch[_] = True;
编辑

consQFold
,如前所述,在Mathematica v8.0.4中工作,但在v8或v7的早期版本中不工作。要纠正这个问题,有两种选择。第一个是显式命名
返回点:

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]

我认为以下内容也很快,比较反向列表不会花费更长的时间:

a = Range[10^7];
f[a_] := Range[Sequence @@ ##, Sign[-#[[1]] + #[[2]]]] &@{a[[1]], a[[-1]]} == a;
Timing[f[a]]
b = Reverse@a;
Timing[f[b]]
编辑

目前最快解决方案的简短测试:

a = Range[2 10^7];
Timing@consQSzab@a
Timing@consQBret@a
Timing@consQBeli@a
(*
{6.5,True}
{0.703,True}
{0.203,True}
*)

我现在确信,贝里萨里乌斯是在故意编写复杂的代码,以此来激怒我-p

我会写:
f=Range[##,Sign[#2-#]]&@@@#[{1,-1}]===#&

另外,我相信花环可能是想写一些东西,比如:

consQFold[a_] := 
 Catch[
  Fold[If[#2 === # + 1, #2, Throw@False] &, a[[1]] - 1, a]; 
  True
 ]

因为时间似乎很重要。我已经将各种方法之间的比较转移到这个社区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]
它生成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
  ]

我对
consQBelisarius
的以下函数、、、和进行了计时

按最左边时间的升序排列:
consQBelisarius
consQWizard
consqcollyer
consQBrett
consQWRMatch
consqzabolcs2
consQWRFold2
consQWRFold3
、以及
consQWRFold

Edit:使用(第二个)重新运行所有函数,而不是
consQTiming
中的
计时。不过,我的平均成绩还是超过了100分。在大多数情况下,没有任何变化,除了最低的两个运行之间有一些变化。所以,把这两条线放在一边,因为它们的时间实际上是相同的


以及尺寸1的列表。我更喜欢你的。快速、实用、紧凑。:-)但是(对我来说)很神秘,在哪里Union@Differences接近于自我记录。-很难决定哪一个是最好的两者都使我的“解决方案”远远落后于性能,但很容易崩溃。设置
a={1,2,3,4,5}
并从那里开始。请查看EDIT:和进一步讨论。您将如何修改您的consQ?@nilo,您可以遵循belisarius的指导,使用
符号
Most[a]+符号[a[[2]]-a[[1]]]===Rest[a]
,因为您正在测试差集是否正好是
{1}
,检查列表是否包含一个整数就足够了,而不是全部检查。或者没有完整性约束:consQ[a_]:=Union@Differences[a] ={1}。酷。很难在您的解决方案和Champion的解决方案之间做出选择。-(我不知道Mathematica有差异函数。)请看一下编辑:和进一步的问题。您将如何修改您的consQ?谢谢您的编辑@Szabolcs-我喜欢你的答案,因为它的可读性、紧凑性和功能性,即使从技术上讲,它可能不是最快的。-解决方案的多样性显示了Mathematica的威力。我不是计时专家,但在比较sec算法速度时,不是在计时要选择的函数吗我这样问是因为我在使用计时而不是绝对计时时得到了不同的结果我对哪个解决方案使用最快的算法感兴趣。@Niloderook,我使用
计时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]
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]
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
  ]