Estou vasculhando um site em busca de informações. Um fragmento contém dois métodos que recuperam os dados e depois os desenha. Tive que processar os dados de forma assíncrona para evitar que o thread principal fosse bloqueado. No entanto, quando executo meu código, fica claro que o processamento assíncrono de dados está ocorrendo fora de ordem e isso está fazendo com que algum índice fique fora dos limites. Não tenho certeza do que fazer. Tentei limitar o paralelismo que não ajudou. o que estou perdendo?
private fun openinsiderGetData(): DataFrame<Any> {
val doc = Jsoup.connect("http://openinsider.com/search?q=TSLA").get()
val table = doc.select(".tinytable")
val dataMap = HashMap<String, ArrayList<String>>()
table.select("thead").select("tr").forEach {row ->
row.getElementsByTag("th").forEach { cell ->
dataMap[cell.text()] = ArrayList<String>()
}
}
// Get the table body cells
val keys = dataMap.keys.toList()
Log.d("Keys", keys.toString())
table.select("tbody").select("tr").forEach {row ->
var index = 0
for (i in 0..row.getElementsByTag("td").size) {
val key = keys[index]
Log.d("Key", key)
index += 1
Log.d("CELL TEXT:", row.getElementsByTag("td")[i].text())
dataMap[key]?.add(row.getElementsByTag("td")[i].text())
Log.d("DATA SO FAR", dataMap.toString())
}
}
Log.d("Map:", dataMap.toString())
val df = emptyDataFrame<Any>()
for (key in dataMap.keys) {
val column = columnOf(dataMap[key]) named key
df.add(column)
}
Log.d("Dataframe:", df.toString())
// process the data further
return df
}
}
private fun setupData() {
lifecycleScope.launch {
withContext(Dispatchers.Default.limitedParallelism(1)) {
data = openinsiderGetData()
val rows = data.values(byRows=true)
Log.d("ROWS:", rows.toString())
}
// TODO - Refactor Draw the table
Meu registro dos meus dados fornece:
{Insider Name=[D], Filing Date=[2023-08-08 20:01:17], 1w=[2023-08-04], Ticker=[TSLA], Title=[Taneja Vaibhav], Trade Type=[CFO, CAO], ΔOwn=[S - Sale+OE], 1d=[$261.00], Owned=[-4,000], Price=[104,504], Qty=[-4%], 6m=[-$1,044,000], X=[], Value=[], Trade Date=[], 1m=[]}
o que está claramente fora de ordem. Estou perplexo sobre como isso acontece e como evitá-lo.
Seu problema não tem nada a ver com o processamento dos dados em paralelo. Na verdade, você não processa nada em paralelo aqui, não importa se limita o paralelismo ou não. Você lançou apenas uma única corrotina, portanto não há nada para executar em paralelo.
Como na sua pergunta anterior, você parece assumir que as chaves em um mapa usam alguma ordem específica, elas têm seus índices. Eles geralmente não o fazem. Depois de adicionar dados ao mapa, se buscarmos suas chaves, as obteremos em ordem aleatória.
Uma maneira de corrigir o problema é usar o
LinkedHashMap
em vez deHashMap
. Esta é uma implementação especial de um mapa, que preserva o pedido de inserção. Melhor ainda, usemutableMapOf<String, List<String>>()
a função que é a forma padrão de criar mapas em Kotlin e abaixo dela usa a extensãoLinkedHashMap
.Uma solução mais explícita seria criar uma lista de chaves enquanto analisa o arquivo
thead
. Ou podemos armazenarArrayList
objetos tanto em um mapa quanto em uma lista:O problema pode estar no seu
HashMap
, pois ele não mantém a ordem de inserção, tente usarLinkedHashMap
.