Исключение области Android: java.lang.IllegalStateException: объект больше недействителен для работы. Удалился ли он другим потоком? [Дубликат]

Использование матричных манипуляций

Позвольте мне предисловие к этому ответу со следующим комментарием:

ЭТО НЕПРАВИЛЬНЫЙ СПОСОБ ДЕЛАТЬ ЭТО. ЭТО ПРЕДОТВРАТЬ НА ЧИСЛЕННУЮ НЕУСТОЙЧИВОСТЬ И БОЛЬШЕ СКОРОСТЬ, ЧТО ДРУГИЕ МЕТОДЫ ПРЕДСТАВЛЕНЫ, ИСПОЛЬЗУЮТСЯ НА ВАШЕМ СОБСТВЕННОМ РИСКЕ.

Сказанное, я не мог устоять перед решением проблемы с динамической точки зрения (и я надеюсь, вы получите свежий взгляд на проблему). В теории это должно работать все время, но вычисления собственных значений могут часто терпеть неудачу. Идея состоит в том, чтобы рассматривать ваш список как поток из строк в столбцы. Если две строки имеют общую ценность, между ними существует соединительный поток. Если бы мы думали об этих потоках как о воде, мы бы увидели, что потоки кластеризуются в маленькие пулы, когда между ними существует соединительный путь. Для простоты я собираюсь использовать меньший набор, хотя он также работает с вашим набором данных:

from numpy import where, newaxis
from scipy import linalg, array, zeros

X = [[0,1,3],[2],[3,1]]

Нам нужно преобразовать данные в потоковый граф. Если строка i втекает в значение j , поместим ее в матрицу. Здесь у нас есть 3 строки и 4 уникальных значения:

A = zeros((4,len(X)), dtype=float)
for i,row in enumerate(X):
    for val in row: A[val,i] = 1

В общем, вам нужно будет изменить 4, чтобы записать количество уникальных значений, которые у вас есть. Если набор представляет собой список целых чисел, начиная с 0, как у нас, вы можете просто сделать это самым большим числом. Теперь мы выполняем разложение по собственным значениям. SVD, если быть точным, поскольку наша матрица не является квадратной.

S  = linalg.svd(A)

Мы хотим сохранить только часть 3х3 этого ответа, поскольку она будет представлять поток пулов. На самом деле нам нужны только абсолютные значения этой матрицы; нам остается только, есть ли поток в этом пространстве cluster .

M  = abs(S[2])

Мы можем представить эту матрицу M как марковскую матрицу и сделать ее явной по нормировке строк. Как только мы это получим, мы вычисляем (слева) разложение собственного значения. этой матрицы.

M /=  M.sum(axis=1)[:,newaxis]
U,V = linalg.eig(M,left=True, right=False)
V = abs(V)

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

idx = where(U > .999)[0]
C = V.T[idx] > 0

Я должен использовать .999 из-за вышеупомянутой числовой неустойчивости. На этом мы закончили! Каждый независимый кластер может теперь вывести соответствующие строки:

for cluster in C:
    print where(A[:,cluster].sum(axis=1))[0]

Что дает, как и предполагалось:

[0 1 3]
[2]

Измените X на lst, и вы get: [ 0 1 3 4 5 10 11 16] [2 8].


Добавление

Почему это может быть полезно? Я не знаю, откуда берутся ваши базовые данные, но что происходит, когда соединения не являются абсолютными? У строки 1 есть запись 3 80% времени - как бы вы обобщили проблему? Метод потока выше работал бы очень хорошо и был бы полностью параметризован этим значением .999, чем дальше от единства, тем слабее ассоциация.


Визуальное представление

Поскольку изображение стоит 1K слов, вот графики матриц A и V для моего примера и ваши lst соответственно. Обратите внимание, как в V разбивается на два кластера (это блок-диагональная матрица с двумя блоками после перестановки), так как для каждого примера было только два уникальных списка!

My Example [/g9] Your sample data [/g10]


Быстрая реализация

Оглядываясь назад, я понял, что вы можете пропустить шаг SVD и вычислить только один decomp:

M = dot(A.T,A)
M /=  M.sum(axis=1)[:,newaxis]
U,V = linalg.eig(M,left=True, right=False)

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

5
задан Yasin Kaçmaz 28 July 2016 в 11:40
поделиться

1 ответ

Итак, вы вызываете adapter.notifyDataSetChanged(), поэтому никакой другой метод notify___ не нужен (изменение набора данных в любом случае отключает анимацию.)

В этом случае самый простой (и наиболее эффективный) способ делать что-то будет, чтобы использовать RealmResults напрямую, а не извлекать каждый элемент в ArrayList, который затем используется точно таким же образом.

Итак, это должно быть как

public static RealmResults<City> getStoredCities(){
        RealmQuery<City> query = getRealmInstance().where(City.class);
        return realm.where(City.class)
                        .findAllSorted("timestamp", Sort.DESCENDING);
}

И

public static void removeCity(City city){
        final String cityName = city.getCityName();
        realm.executeTransaction(new Realm.Transaction() {
            @Override
            public void execute(Realm realm) {
                RealmResults<City> result = realm.where(City.class).equalTo("cityName", cityName).findAll();
                result.deleteAllFromRealm();
            }
        });
}

И

builder.setPositiveButton(getString(R.string.ok), new DialogInterface.OnClickListener() {
    @Override
    public void onClick(DialogInterface dialogInterface, int i) {
        RealmHelper.removeCity(getItem(position));
    }
});

И

// dependency: compile 'io.realm:android-adapters:1.3.0' // <-- for Realm 3.x+, use 2.0.0
public class CityListAdapter extends RealmRecyclerViewAdapter<City, CityListViewHolder> { 

    OnItemClickListener onItemClickListener;
    OnItemLongClickListener onItemLongClickListener;

    public CityListAdapter(@NonNull Context context, 
                           @Nullable OrderedRealmCollection<City> data, 
                           OnItemClickListener onItemClickListener, 
                           OnItemLongClickListener onItemLongClickListener) {
        super(context, data, true);
        this.onItemClickListener = onItemClickListener;
        this.onItemLongClickListener = onItemLongClickListener;
    }


    @Override
    public CityListViewholder onCreateViewHolder(ViewGroup parent, int viewType) {
        View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.city_item_navigation_viewholder, parent, false);
        CityListViewholder cityListViewholder = new CityListViewholder(view, parent.getContext());
        return cityListViewholder;
    }

    @Override
    public void onBindViewHolder(CityListViewholder holder, int position) {
        holder.cityName.setText(getItem(position).getCityName());
        holder.bindClick(position, onItemClickListener);
        holder.bindLongClick(position, onItemLongClickListener);
    }

    public static class CityListViewholder extends RecyclerView.ViewHolder {
        TextView cityName;
        ImageView cityIcon;

        public CityListViewholder(View itemView, 
                                  Context context) {
            super(itemView);
            cityName = (TextView)itemView.findViewById(R.id.city_name);
            cityIcon = (ImageView)itemView.findViewById(R.id.city_icon);
        }

        public void bindClick(final int position, final OnItemClickListener onItemClickListener){
            itemView.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    onItemClickListener.onItemClick(position);
                }
            });
        }

        public void bindLongClick(final int position, final OnItemLongClickListener onItemLongClickListener) {
            itemView.setOnLongClickListener(new View.OnLongClickListener() {
                @Override
                public boolean onLongClick(View view) {
                    onItemLongClickListener.onItemLongClick(position);
                    return true;
                }
            });
        }
    }
}

Используя RealmRecyclerViewAdapter, вызывается notifyDataSetChanged() всякий раз, когда ваши результаты меняются.

4
ответ дан EpicPandaForce 16 August 2018 в 00:51
поделиться
  • 1
    Я в настоящее время реализую :) - В методе remove getdata (), похоже, не распознается RealmHelper.removeCity(getData().get(position)); – Isabelle 30 July 2016 в 07:38
  • 2
    getItem(position) также работает, если я знаю правильно, хотя getData() работал для меня – EpicPandaForce 30 July 2016 в 09:06
  • 3
    Хотя вы, вероятно, имеете в виду код диалогового построителя. Это должно быть results.get(position), но я не уверен, где вы используете код. – EpicPandaForce 30 July 2016 в 09:07
  • 4
    Я мог только вернуться к коду и хотел бы еще раз поблагодарить вас за вашу помощь. getData не работает для меня, имеет ли смысл использовать RealmHelper.getStoredCities (). get (position)? – Isabelle 4 August 2016 в 11:51
  • 5
    getData() - метод RealmRecyclerViewAdapter – EpicPandaForce 4 August 2016 в 12:42
Другие вопросы по тегам:

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