我有9个整数的列表,其值分别为1,-1、0,例如:
[-1, 0, 0, 1, -1, -1, 1, 1, 0]
我想做的是从这个列表创建一个列表列表,其中每个列表仅包含一个更改,并且始终不同。对于每个-1,我想将其更改为0。
示例:
从列表中:
[-1,0,0,1,-1,-1,1,1,0],
我想得到结果:
[ [ 0, 0, 0, 1, -1, -1, 1, 1, 0]
, [-1, 0, 0, 1, 0, -1, 1, 1, 0]
, [-1, 0, 0, 1, -1, 0, 1, 1, 0]
]
因此,每个列表仅更改了一个值,并且每个列表都有不同的值。我什至不知道如何开始。
答案 0 :(得分:1)
您始终需要做的第一件事就是弄清楚函数的类型签名。根据您的情况
lister :: [Int] -> [[Int]]
然后,当您要遍历列表但要跟踪已更改的索引时,一种简单的方法是列出列表的列表(很难理解,只看代码即可)然后压缩它及其索引。然后,对于每个列表,将元素切换到该位置。这是你的代码
lister :: [Int] -> [[Int]]
lister ls = [switch i l | (i,l) <- zip [0..9] (repeat ls)]
然后,您需要一个切换功能,以根据您的规则将元素切换到第i个位置:
switch :: Int -> [Int] -> [Int]
switch 0 ls = ls
switch n ls = [if i == n && x == -1 then 0 else x | (i,x) <- zip [1..] ls]
请注意,这将返回9个列表,原始列表中的每个元素一个。因此,它包含一些重复项。您可以使用nub
中的Data.List
消除它们,请注意,因为它是O(n^2)
这是您的完整代码:
import Data.List
lister :: [Int] -> [[Int]]
lister ls = nub [switch i l | (i,l) <- zip [0..9] (repeat ls)]
switch :: Int -> [Int] -> [Int]
switch 0 ls = ls
switch n ls = [if i == n && x == -1 then 0 else x | (i,x) <- zip [1..] ls]
答案 1 :(得分:1)
显然,这是一个非常具体的问题。从更大的角度看通常是有用的:这是什么特殊情况?显然,在这里,我们正在浏览一个列表,并且可能会看到我们希望以零种或多种方式替换的元素。此外,我们希望看到有几种方法可以进行有限数量的此类替换。因此,在考虑如何专门解决我们最初的问题之前,让我们先实施一般情况:
import Control.Applicative (Alternative, empty, (<|>))
replaceNTimes :: Alternative f => (a -> f a) -> Int -> [a] -> f [a]
replaceNTimes _ 0 xs = pure xs
replaceNTimes _ _ [] = empty
replaceNTimes f n (x:xs) = replaceHere <|> keepLooking
where replaceHere = (:) <$> f x <*> replaceNTimes f (n - 1) xs
keepLooking = (x:) <$> replaceNTimes f n xs
如果我们有一个零替换的“预算”,我们只返回列表的剩余部分。如果我们有剩余预算,但列表为空,则会中止,因为我们无法进行预期的更换次数。否则,我们将咨询我们的replacement-suggester函数,以查看在当前位置上哪些替换是合法的,然后选择创建其中一个替换并使用较小的N进行递归,或者选择不替换并使用相同的N进行递归。
使用此工具,最初的问题很容易:我们将N专门化为1(精确地进行一次替换),并提供了仅建议将0替换为-1的替换功能:
replaceSingleNegativeOneWithZero :: [Int] -> [[Int]]
replaceSingleNegativeOneWithZero = replaceNTimes go 1
where go (-1) = [0]
go _ = []
并进行测试以确保我们获得了预期的输出:
*Main> replaceSingleNegativeOneWithZero [-1,0,0,1,-1,-1,1,1,0]
[ [0,0,0,1,-1,-1,1,1,0]
, [-1,0,0,1,0,-1,1,1,0]
, [-1,0,0,1,-1,0,1,1,0]]
答案 2 :(得分:0)
另一种尝试:
library(RSQLite)
library(dplyr)
#create dummy SQL database
set.seed(123)
tax<-tibble(taxpayer_id=1:10,income=runif(10,50,60),income_misc=runif(10,0,5)) %>%
mutate(income_misc=ifelse(income_misc<2,NA,income_misc))
con <- dbConnect(RSQLite::SQLite(), ":memory:")
dbWriteTable(con,"tax_tbl",tax,overwrite=TRUE)
# now extract
tax_db <- tbl(con, 'tax_tbl')
tax_db
#> # Source: table<tax_tbl> [?? x 3]
#> # Database: sqlite 3.22.0 [:memory:]
#> taxpayer_id income income_misc
#> <int> <dbl> <dbl>
#> 1 1 52.9 4.78
#> 2 2 57.9 2.27
#> 3 3 54.1 3.39
#> 4 4 58.8 2.86
#> 5 5 59.4 NA
#> 6 6 50.5 4.50
#> 7 7 55.3 NA
#> 8 8 58.9 NA
#> 9 9 55.5 NA
#> 10 10 54.6 4.77
tax <- tax_db %>%
as_tibble() %>% #have to create a data frame, not database, to modify NAs
mutate_all(funs(replace(., is.na(.), 0)))
dbDisconnect(con)
tax
#> # A tibble: 10 x 3
#> taxpayer_id income income_misc
#> <dbl> <dbl> <dbl>
#> 1 1 52.9 4.78
#> 2 2 57.9 2.27
#> 3 3 54.1 3.39
#> 4 4 58.8 2.86
#> 5 5 59.4 0
#> 6 6 50.5 4.50
#> 7 7 55.3 0
#> 8 8 58.9 0
#> 9 9 55.5 0
#> 10 10 54.6 4.77
Created on 2019-02-20 by the reprex package (v0.2.1)
用法:
zeros :: [Int] -> [Int] -> [[Int]]
zeros _ [] = []
zeros h (x:xs) = [h ++ newX:xs] ++ zeros nextH xs
where newX = if x == (-1) then 0 else x
nextH = h ++ [x]
switch xs = ((filter (/= xs)) . (zeros [])) xs