Как насчет простых проверок?
function p
| p < 0 = []
| p < 7 = [0..6]
| p < 14 = [7..13]
| p < 21 = [14..20]
| otherwise = []
Это будет быстрее, и для некоторых приложений использование меньше памяти.
Если вы не хотите выполнять проверку границ (но проверку элемента), вы все равно можете использовать сокращенную нотацию списка.
В качестве альтернативы, можно построить вспомогательную функцию, что итерация по спискам:
helper (x:xs) p | elem p x = x
| otherwise = helper xs p
helper [] _ = []
function = helper [[0..6],[7..13],[14..20]]
Хотя это на самом деле больше, вы можете легко расширить function
использовать другие списки. Обратите внимание, однако, что эта функция будет медленнее, так как elem
требует O (n) время, тогда как проверка границ принимает O (1) время.
Вы можете также - как это предлагается в @jamshidh's answer построить Data.Map
, который является структура данных, которая гарантирует время O (журнал N) подстановок:
import Data.Map (Map)
import qualified Data.Map as Map
import Data.Maybe(fromMaybe)
helper2 :: Ord a => [[a]] -> a -> [a]
helper2 lst p = fromMaybe [] $ Map.lookup p (Map.fromList $ concatMap (\x -> zip x (repeat x)) lst)
function = helper2 [[0..6],[7..13],[14..20]]
Для этой последней части, он генерирует (\x -> zip x (repeat x))
генерирует список кортежей, содержащий элемент списка e
и весь список l
. Например:
Prelude> (\x -> zip x (repeat x)) [0..6]
[(0,[0,1,2,3,4,5,6]),(1,[0,1,2,3,4,5,6]),(2,[0,1,2,3,4,5,6]),(3,[0,1,2,3,4,5,6]),(4,[0,1,2,3,4,5,6]),(5,[0,1,2,3,4,5,6]),(6,[0,1,2,3,4,5,6])]
Это работает следующим образом: x
унифицирует со списком, например [0,1,2,3,4,5,6]
, теперь мы применяем zip
функцию [0,1,2,3,4,5,6]
и на бесконечном списке [[0,1,2,3,4,5,6],[0,1,2,3,4,5,6],[0,1,2,3,4,5,6],....]
. zip
генерирует кортежи до тех пор, пока оба элемента содержат элементы списка, поэтому он принимает первый элемент от [0,1,..,6]
и первый от [[0,1,..,6],[0,1,..,6],[0,1,..,6],...]
, поэтому полученный результат равен (0,[0..6])
, затем он берет второй элемент 1
из списка, а второй элемент из функции repeat
, таким образом (1,[0..6])
. Он продолжает делать это - хотя и лениво - до тех пор, пока один из списков не будет исчерпан, что имеет место для первого списка.
являются блоки номеров всегда непрерывные значения в группах 7? – jamshidh
@jamshidh Они всегда в группах по 7, но не всегда содержат последовательные значения. – heyyo
Для этой конкретной функции у меня возникло бы желание написать что-то вроде 'function p = [lo .. lo + 6], где lo = 7 * div p 7'. –