Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Observable if the array element is changed

How I can write this code with a single line?

public class RadGridColumnObservable
{
    public RadGridColumnObservable(RadGridView grid, IMessageBus messageBus)
    {
        this.grid = grid;
        this.messageBus = messageBus;
    }

    public IDisposable Initialize()
    {
        CreateStates();

        return Observable
            .Interval(TimeSpan.FromSeconds(1))
            .Subscribe(_ => CheckUp());
    }

    //

    private readonly RadGridView grid;
    private readonly IMessageBus messageBus;
    private readonly List<bool> states = new List<bool>();

    //

    private void CreateStates()
    {
        states.Clear();
        states.AddRange(grid.Columns.Select(it => it.IsVisible));
    }

    private void CheckUp()
    {
        if (states.SequenceEqual(grid.Columns.Select(it => it.IsVisible))) return;

        CreateStates();
        messageBus.Publish(new NotifyMessage(MessageTypes.HistoryColumnsChanged));
    }
}

The idea is: I want to check if the IsVisible property is changed.

I don't like to use this line:

private readonly List<bool> states = new List<bool>();
like image 661
Alex Soryn Avatar asked Apr 08 '26 02:04

Alex Soryn


1 Answers

You could get your IsVisible values with something like this:

private IObservable<List<bool>> CreateStatesObservable()
{
    return Observable.Interval(TimeSpan.FromSeconds(1))
                        .Select(_ => grid.Columns.Select(it => it.IsVisible));
}

And then use Scan to keep track of your previous value:

public void Initialize()
{
    var observable = 
            CreateStatesObservable()
                        .Scan(
                            (prev: default(List<bool>), actual: default(List<bool>)),
                            (acc, c) => (acc.actual, current))
                        .Where(values => !values.actual.SequenceEqual(values.prev))
                        .Select(_ => true);
}

Or you could use Defer and do something like this:

public void Initialize2()
{
    var observable = CreateStatesObservable();

    var deferred =
        Observable.Defer(
                      () =>
                      {
                          List<bool> previous = null;

                          return observable.Select(
                              values =>
                              {
                                  if (previous is null)
                                  {
                                      previous = values;
                                      return false;
                                  }

                                  if (!values.SequenceEqual(previous))
                                  {
                                      previous = values;
                                      return true;
                                  }

                                  return false;
                              });
                      })
                  .Where(value => value);
}

Both options should give you an observable which only produces a value when one of the columns IsVisible has changed. (That value just being a true)

Edit:

You can also use DistinctUntilChanged() with your own IEqualityComparer like this:

class ListComparer : IEqualityComparer<List<bool>>
{
    bool IEqualityComparer<List<bool>>.Equals(List<bool>? a, List<bool>? b)
    {
        if (a is null && b is null)
        {
            return true;
        }
        
        if (a is null || b is null)
        {
            return false;
        }
        
        return a.SequenceEqual(b);
    }

    int IEqualityComparer<List<bool>>.GetHashCode(List<bool> obj)
    {
        return obj.GetHashCode();
    }
}

And then use it like this:

public void Initialize()
{
    var observable = 
            CreateStatesObservable()
                        .DistinctUntilChanged(new ListComparer())
                        .Select(_ => true);
}
like image 140
Beastlike Avatar answered Apr 10 '26 16:04

Beastlike



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!