7
votes

Combinelats, mais seulement pousser pour la gauche

J'ai besoin d'implémenter une version de combinelatst code> (je l'appellerai withlaest code> ici) qui appelle le sélecteur pour chaque élément de gauche et le dernier élément de la à droite. Il ne devrait pas pousser pour les articles sur le bon changement seulement.

Je pense que cela soit construit observable.create code> ou une combinaison d'extensions existantes n'est pas particulièrement importante; Je vais faire une méthode d'extension "boxée" de toute façon. P>

Exemple fort> p> xxx pré>

devrait donner p >

var lr = right.ObserveOn(Scheduler.TaskPool).Latest();
left.Select(l => l + " " + lr.First()).Dump();


5 commentaires

Vous souhaitez effectuer ces combinaisons W / existants uniquement ou une implémentation utilisant créer () une option?


Votre exemple ne correspond pas à ce que je m'attendais à votre description. Le premier élément renvoyé dans votre exemple semble être déclenché par un changement de droite observable. Devrait-il WASLATEST déclencheur sur la première droite s'il y a déjà des éléments de gauche?


Voir «CombinaisonLaest» dans Ma réponse ici - très modèle similaire.


@Gideon engelberth: d'accord. Cela m'a laissé de perplexe aussi. Selon la description, l'algorithme devrait donner uniquement "3 2" seulement.


Pouvez-vous écrire votre réponse comme une réponse plutôt qu'une modification à la question?


6 Réponses :


0
votes

Voici le chemin hacky en utilisant Create - ne l'a pas réellement construit, MEA CULPA s'il ne fonctionne pas réellement :)

public static IObservable<TRet> WithLatest<TLeft, TRight, TRet>(
        this IObservable<TLeft> lhs, 
        IObservable<TRight> rhs, 
        Func<TLeft, TRight, TRet> sel)
{
    return Observable.Create<TRet>(subj => {
        bool rhsSet = false;
        bool deaded = false;
        var latestRhs = default(TRight);

        Action onDeaded = null;

        var rhsDisp = rhs.Subscribe(
            x => { latestRhs = x; rhsSet = true; }, 
            ex => { subj.OnError(ex); onDeaded(); });

        var lhsDisp = lhs
            .Where(_ => deaded == false && rhsSet == true)
            .Subscribe(
                x => subj.OnNext(sel(x, latestRhs)),
                ex => { subj.OnError(ex); onDeaded(); },
                () => { subj.OnCompleted(); onDeaded(); });

        onDeaded = () => {
            deaded = true;
            if (lhsDisp != null) {
                lhsDisp.Dispose();
                lhsDisp = null;
            }
            if (rhsDisp != null) {
                rhsDisp.Dispose();
                rhsDisp = null;
            }
        };

        return onDeaded;
    });
}


3 commentaires

Je reçois "1 0", "2 0" pour mon exemple.


Whoops, ma clause Where était mauvaise, essayez-la maintenant


maintenant c'est juste "3 2" - quelle est la solution correcte en fonction de l'exigence: seulement pousser pour la gauche



4
votes

J'ai aussi eu le même besoin d'un Combinelatst qui "ne pousse que pour la gauche".

J'ai fait la solution une "surcharge" de observable.Sample , parce que c'est ce que la méthode fait:
Il échantillon un source (à droite) avec un échantillonneur (à gauche), avec la capacité supplémentaire de fournir un RESUMECTEnector (comme dans Combinelatst). < / p> xxx


1 commentaires

Utilisation pour l'exemple ci-dessus: droite.sample (gauche, (r, l) => l + "" + r) .Dump (); il produit "3 2" qui est imo correct



1
votes

Basé sur la solution choisie par l'auteur Post, je pense qu'il y a une solution encore plus simple utilisant distinctuntilchanged : xxx

ou même xxx

Si vous ne vous souciez que de valeurs distinctes de Leftsource


0 commentaires

5
votes

Vous pouvez le faire en utilisant les opérateurs existants.

Func<int, int, string> selector = (l, r) => l + " " + r;

var query = right.Publish(rs => left.Zip(rs.MostRecent(0), selector).SkipUntil(rs));
  • Publish code> nous assure que nous ne vous abonnez à ce que à droite code> une fois et partagez l'abonnement parmi tous les abonnés à rs code>. p> li>

  • mostrecent code> tourne un iobservable code> dans un ienumerable code> qui donne toujours la valeur la plus récente de la source observable. p> li>

  • zip code> entre iobservable code> et ienumerable code> émet une valeur à chaque fois que l'observable émet une valeur. li>

  • SPAPUNTIL code> saute les paires (l, r) code> qui se produisent avant droite code> émet une valeur. P> ul> p>


0 commentaires

0
votes

J'ai fait un opérateur RX pour le projet aujourd'hui qui fait cela.

Voici mes solutions: P>

    public static IObservable<Tuple<TSource, TTarget>> JoinLeftSoft<TSource, TTarget>(
        this IObservable<TSource> source, IObservable<TTarget> right)
    {
        return source
            .Select(x => new Tuple<object, TSource>(new object(), x))
            .CombineLatest(right, (l, r) => new Tuple<object, TSource, TTarget>(l.Item1, l.Item2, r))
            .DistinctUntilChanged(t => t.Item1)
            .Select(t => new Tuple<TSource, TTarget>(t.Item2, t.Item3));
    }


0 commentaires

1
votes

sur le dernier system.reactive , nous pouvons utiliser withLatestFrom méthode d'extension. xxx

Le résultat serait inférieur correctement. xxx


0 commentaires