Haskell Split String для каждого символа в список строки размера n [дубликат]

NullPointerException s - исключения, возникающие при попытке использовать ссылку, которая указывает на отсутствие местоположения в памяти (null), как если бы она ссылалась на объект. Вызов метода по нулевой ссылке или попытка получить доступ к полю нулевой ссылки вызовет функцию NullPointerException. Они наиболее распространены, но другие способы перечислены на странице NullPointerException javadoc.

Вероятно, самый быстрый пример кода, который я мог бы придумать для иллюстрации NullPointerException, be:

public class Example {

    public static void main(String[] args) {
        Object obj = null;
        obj.hashCode();
    }

}

В первой строке внутри main я явно устанавливаю ссылку Object obj равной null. Это означает, что у меня есть ссылка, но она не указывает на какой-либо объект. После этого я пытаюсь обработать ссылку так, как если бы она указывала на объект, вызывая метод на нем. Это приводит к NullPointerException, потому что нет кода для выполнения в местоположении, на которое указывает ссылка.

(Это техничность, но я думаю, что она упоминает: ссылка, которая указывает на null, равна 't то же, что и указатель C, указывающий на недопустимую ячейку памяти. Нулевой указатель буквально не указывает на в любом месте , который отличается от указаний на местоположение, которое оказывается недопустимым.)

5
задан iobender 6 July 2014 в 21:08
поделиться

2 ответа

Вы можете использовать tails:

gather n l = filter ((== n) . length) $ map (take n) $ tails l

или использовать takeWhile вместо filter:

gather n l = takeWhile ((== n) . length) $ map (take n) $ tails l

EDIT: вы можете удалить шаг фильтра на отбрасывая последние n элементы списка, возвращенные из tails, как предложено в комментариях:

gather n = map (take n) . dropLast n . tails
  where dropLast n xs = zipWith const xs (drop n xs)
14
ответ дан Lee 20 August 2018 в 10:20
поделиться
  • 1
    Я использовал бы takeWhile вместо filter, но это довольно скромная оптимизация. – Carl 6 July 2014 в 21:16
  • 2
    также может использовать (iterate (drop 1) s) вместо $ tails l ... – גלעד ברקן 6 July 2014 в 21:38
  • 3
    Это кажется семантически правильным, но оперативно немного грубым: проверка каждой длины подсети кажется слишком большой работой. Существует стандартный трюк, говорящий «взять все, кроме последних n элементов списка», который является \xs -> zipWith const xs (drop n xs); возможно, вы могли бы использовать этот трюк здесь. – Daniel Wagner 7 July 2014 в 00:13
  • 4
    @ DanielWagner - Спасибо за предложение, это намного чище. – Lee 7 July 2014 в 00:47

Отбрасывание хвостов может быть организовано автоматически, благодаря свойствам zipping ,

import Data.List (tails)

g :: Int -> [a] -> [[a]]
g n = foldr (zipWith (:)) (repeat []) . take n . tails

, или просто transpose . take n . tails. Тестирование:

Prelude Data.List> g 3 [1..10] [[1,2,3], [2,3,4], [3,4,5], [4,5,6], [5,6,7], [6,7,8], [7,8,9], [8,9,10]] Prelude Data.List> транспонировать. возьмите 3. хвосты $ [1..10] [[1,2,3], [2,3,4], [3,4,5], [4,5,6], [5,6,7], [ 6,7,8], [7,8,9], [8,9,10], [9,10], [10]]

5
ответ дан Will Ness 20 August 2018 в 10:20
поделиться
  • 1
    То, что мне так нравится в обоих, заключается в том, что они выполняют обе строки и списки Int. Параметры вызова могут быть улучшены, но это не важно. Mine будет делать Int, но не строки без дополнительной логики. .... gv no sz = zipWith enumFromTo [1..no] [sz ..] & gt; & GT; & GT; & GT; gv 3 4 для списка из трех списков элементов. – fp_mora 2 April 2018 в 22:24
  • 2
    пункт здесь состоит в том, чтобы переупорядочить данный список, а не воссоздавать его. zipWith enumFromTo создает списки целых чисел, которые имитируют результат, но что, если нам нужно изменить результат sort ([1,4..20] ++ [1,5..30])? Реорганизация игнорирует природу элементов и просто управляет структурой списка , независимо от того, что она содержит. Как и в списке, была цепочка ящиков (каждая из которых содержит некоторый элемент), и мы работаем с полями, а не с тем, что в . (флаги not фактически сохраняют значения, а удерживают указатели для этих значений - каждый ящик содержит один указатель). – Will Ness 3 April 2018 в 07:39
  • 3
    Это то, что подразумевается под «параметрией» в Haskell, когда мы говорим «[a] является параметрическим типом,« списком » 'something' < / i>, что бы это ни было " - что something является параметром a в типе [] a, то есть [a]. Поэтому, когда мы переустанавливаем список, мы создаем новую «структуру списка». то есть новые цепочки ящиков, содержащие новые указатели с теми же значениями , которые были в исходных полях. Так же, как это делается в Лиспе. – Will Ness 3 April 2018 в 07:39
  • 4
    В Lisp указатель поля может быть изменен с помощью set-car! или set-cdr!. Не так в Хаскелле. Но концептуально эта модель предотвращает чрезмерное копирование значений при перестановках, что было бы неизбежным, если бы мы сказали, что у нас есть коробки со значениями, фактически находящимися в in (новая цепочка будет хранить копии значений в своих полях). Конечно, в Haskell, с его ссылочной прозрачностью, скопированное значение нельзя отличить от нового указателя на одно и то же значение (с нормальными значениями Haskell), за исключением эффектов performance (размер памяти, скорость , количество GC (сбор мусора) и т. д.). – Will Ness 3 April 2018 в 07:49
  • 5
    [# t, # t, # t] Racket forwent set-car и т. д. Он нарушает, как вы сказали, Ref Transparency, а также неизменность. Список - это необходимый параметр, который я вижу сейчас. Рекурсивная функция использует хвост. принимать & amp; длина. Мне нравится следующее лучше, чем мой последний рекурсивный, и он обрабатывает любой список или строку, спасибо вам большое. , , g2 sz ls = [принять sz t | t & lt; - хвосты ls, длина t & gt; = sz] – fp_mora 3 April 2018 в 16:09
Другие вопросы по тегам:

Похожие вопросы: