записывать записи как раз в то время, когда значение (для id чего-либо) меняется - PullRequest
1 голос
/ 26 июля 2011

Как писать записи как раз в то время, когда значение для id чего-то меняется?идентификатор для каждой записи, когда ture-> false и false-> true для некоторого списка?

например таблица

id value
 1 0
 2 0
 2 0
 2 0
 1 0
 2 1 --> the only changes here
 2 1
 1 0
 2 0 --> and here (node with id 2 changed 1 -> 0 )
 1 1 --> node with id 1 changed 0 -> 1     

таблица результатов

2 1
2 0
1 1

моя идеяне функционально и немного странно, я думаю о функциональном или linq способе сделать то же самое.

                        let oop = ref (filteredsq
                                       |> Seq.distinctBy(fun (node,v,k) -> k) 
                                       |> Seq.map(fun (node,v,k) -> k, false )
                                       |> Array.ofSeq )
                        [for (node,value,key) in filteredsq do
                            let i = ref 0
                            for (k,v) in !oop do
                                if key = k && value <> v then
                                    (!oop).[!i] <- (k,value)
                                    yield node
                            i := !i + 1 ]

Спасибо

Ответы [ 5 ]

3 голосов
/ 26 июля 2011

Я думаю, что если вы определите функцию, подобную следующей:

let getChanges f items =
  items
  |> Seq.map (fun x -> f x, x)
  |> Seq.pairwise
  |> Seq.choose (fun ((a, _), (b, x)) -> if a <> b then Some x else None)

Тогда вы можете сделать:

filteredsq
|> Seq.groupBy (fun (_, _, k) -> k)
|> Seq.collect (fun (_, items) ->
  items 
  |> getChanges (fun (_, value, _) -> value)
  |> Seq.map (fun (node, _, _) -> node))
|> Seq.toList
1 голос
/ 26 июля 2011

Я бы просто использовал внутренний изменяемый словарь, чтобы отслеживать последние просмотренные значения для каждого ключа и выход (ключ, значение), когда любое значение отличается от последнего значения в этом ключе:

let filterChanges (s:('a*'b) seq) =   
    let dict = new System.Collections.Generic.Dictionary<'a,'b>()
    seq {
        for (key,value) in s do
            match dict.TryGetValue(key) with
            | false,_ -> dict.[key] <- value
            | true,lastValue -> 
                if lastValue <> value then
                    yield (key,value)
                    dict.[key] <- value
    }

Тест:

> filterChanges [(1,0);(2,0);(2,0);(2,0);(1,0);(2,1);(2,1);(1,0);(2,0);(1,1)];;
val it : seq<int * int> = seq [(2, 1); (2, 0); (1, 1)]
1 голос
/ 26 июля 2011

Обновлено

open System.Collections.Generic

let filter (acc:'a) (f:('a -> 'b -> bool * 'a)) (s:'b seq) = 
    let rec iter (acc:'a) (e:IEnumerator<'b>) = 
        match e.MoveNext() with
        | false -> Seq.empty 
        | true -> match f acc e.Current with
                  | (true,newAcc) -> seq { yield e.Current; yield! iter newAcc e}
                  | (false,newAcc) -> seq { yield! iter newAcc e}
    iter acc (s.GetEnumerator())

let skipUntilChange (f : 'a -> 'b) (s : 'a seq) = 
    s |> Seq.skip 1
    |> filter (s |> Seq.head |> f)
        (fun a b -> if a = f b then false,f b else true,f b)

[(1,0);(2,0);(2,0);(2,0);(1,0);(2,1);(2,1);(1,0);(2,0);]
|> Seq.mapi (fun c (i,v) -> (i,v,c))
|> Seq.groupBy (fun (i,v,c) -> i)
|> Seq.map (snd >> skipUntilChange (fun (_,v,_) -> v))
|> Seq.concat |> Seq.sortBy (fun (i,v,c) -> c)
|> Seq.map (fun (i,v,c) -> (i,v))
|> printfn "%A"
1 голос
/ 26 июля 2011

Я не уверен, полностью ли я понимаю ваш вопрос, но следующее дает правильный вывод в соответствии с вашим образцом. Идея состоит в том, чтобы сначала отфильтровать значения, которые не имеют правильного ключа, а затем использовать Seq.pairwaise (как в решении jpalmer), чтобы найти места, где значение изменяется:

let input = [ (1, 0); (2, 0); (2, 0); (2, 0); (1, 0); (2, 1); (2, 1); (1, 0); (2, 0) ]

let findValueChanges key input =
  input 
  |> Seq.filter (fun (k, v) -> k = key) // Get values with the right key
  |> Seq.pairwise                       // Make tuples with previous & next value
  |> Seq.filter (fun ((_, prev), (_, next)) -> prev <> next) // Find changing points
  |> Seq.map snd                        // Return the new key-value pair (after change)

Если вы хотите найти изменения для всех различных ключей, то вы можете использовать Seq.groupBy, чтобы найти все возможные ключи (тогда вам не понадобится первая строка в findValueChanges):

input 
|> Seq.groupBy fst
|> Seq.map (fun (k, vals) -> findValueChanges k vals)

(Для вашего ввода значения для клавиши 1 не изменяются, поскольку значение всегда 1, 0)

1 голос
/ 26 июля 2011

Я бы сделал что-то вроде

List
|> List.toSeq
|> Seq.pairwise
|> Seq.pick (fun ((fa,fb),(sa,sb)) -> if fb <> sb then Some(sa,sb) else None)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...