How to get specific items using jsoup - android

I'm using this code to select a URL in div tag
Elements mElements = doc.select("a[class^=titr]");
Element linkElement = mElements.select("a").first();
linkElement.attr("href");
but in this cod I just can see first item Because the method is first();
how can I specific that I want to select for example item 0 to 20 instead of first ??

The mElements is returned as a List<Element> - try mElements.get(0) for each one; for all of them iterated:
print("\nElements: (%d)", mElements.size());
for (Element link : mElements) {
print(" * %s <%s> (%s)", link.tagName(),link.attr("abs:href"), link.attr("rel"));
}
http://jsoup.org/apidocs/org/jsoup/select/Elements.html
This is however probably not recommended, since arrays change over time; perhaps you want a better selector method.
http://jsoup.org/cookbook/extracting-data/selector-syntax

Related

Remove first 3 letters from String in list Dart

I want to remove the first 3 letters from every item (String) in my List.
My Listitems look like this:
{2: test1.mp4
3: test2.mp4
4: test3.mp4
10: test4.mp4
11: test5.mp4
I want to remove the "{2: " from the firs item and for every other item i want to remove the number + the space, so that i only have the file name.
the substring method is the solution for your case :
String text = "11: test5.mp4";
String result = text.substring(3); // test5.mp4
and if you just want to remove extra space on sides, use trim method
String text = " test5.mp4 ";
String result = text.trim(); // test5.mp4
It will probably be better to use split() instead of trimming off the white space and using a set index.
const track = '11: test5.mp4';
final splitted = track.split(': ');
print(splitted); // [11, test5.mp4];
Currently it's a little bit unclear how your list looks exactly. I am assuming, you have the following list:
List<String> myList = [
"2: test1.mp4",
"3: test2.mp4",
"4: test3.mp4",
"10: test4.mp4",
"11: test5.mp4",
];
In this case, it's not necessarily only the first 3 letters that you want to remove. A scalable solution would be the following:
final List<String> myList = [
"2: test1.mp4",
"3: test2.mp4",
"4: test3.mp4",
"10: test4.mp4",
"11: test5.mp4",
];
//We are splitting each item at ": ", which gives us a new array with two
//items (the number and the track name) and then we grab the last item of
//that array.
final List<String> myFormatedList = myList.map((e) => e.split(": ").last).toList();
print(myFormatedList);
//[test1.mp4, test2.mp4, test3.mp4, test4.mp4, test5.mp4]

How do you call a variable created earlier in a when in kotlin?

I'm trying to list the first 100 of a shuffled list. I'm telling it to shuffle if the list is at 0 and then increment. I then am trying to call that list in another section of the when but it's not working. How can I accomplish this?
when (countF) {
0 -> {
//shuffle at 0
val randomChaos = chaosList.asSequence().shuffled().take(chaosList.count()).toList()
cResult.text = randomChaos.elementAt(countF) + countF + "\n\n\n\n\n\n\n\n" + this.cResult.text
countF++
}
1-99 -> {
//show 1-99
cResult.text = randomChaos.elementAt(countF) + countF + "\n\n\n\n\n\n\n\n" + this.cResult.text
countF++
}
100 -> countF = 0
You would need to create the val randomChaos before the when enclosure for it to be available in the scope of multiple branches of the when statement.
That said, the way you're getting a random element is very convoluted. take(chaosList.count()) is completely redundant. And since you don't use multiple sequence operators, creating a sequence is also redundant. Finally, you are only pulling a single item from the random list, so it's unnecessary to create a shuffled list in the first place. Using elementAt() on a shuffled list is no different than picking any element out of that shuffled list, or simply picking a random item out of a list that isn't shuffled at all.
Also, the first two branches of your when statement currently would produce exactly the same results so they can be merged.
Based on what you described, I'm guessing you had this when statement inside a loop that tries to run it 100 times so you can list all the items. For that to work, you would need to shuffle the list one time outside the loop, and then you could iterate its elements in the loop.
However, there are functions that can make it easier to do what you're suggesting. Here's an example:
val randomChaos = chaosList.shuffled()
cResult.text = randomChaos.asSequence()
.take(100)
.withIndex()
.joinToString("\n") { (i, value) ->
"$value-$i"
}
In this case, using a Sequence helps avoid creating an intermediate list to hold the first 100 values.
var randomChaos = chaosList.shuffled()
fun cShuf() { randomChaos = chaosList.shuffled() }
cRoll.setOnClickListener() {
cResult.movementMethod = ScrollingMovementMethod()
if (countF < 1) { cShuf() }
cResult.text = randomChaos.elementAt(countF) + "\n\n\n\n\n\n\n\n" + this.cResult.text
countF++
if (countF > 100) countF = 0
}
I have figured out how to use a function to generate a new shuffe of the list once I've hit > 100 shown.
My issue with making it a function was I was trying to use val variable in the function but the variable already existed so I didn't need to use val, just the name of the variable.

Google Sheets API v4 - How to get the last row with value?

How to get the last row with value in the new Google Sheets API v4 ?
i use this to get a range from a sheet:
mService.spreadsheets().values().get("ID_SHEET", "Sheet1!A2:B50").execute();
how to detect the last row with value in the sheet ?
You can set the range to "A2:D" and this would fetch as far as the last data row in your sheet.
I managed to get it by counting the total rows from current Sheets.
Then append the data to the next row.
rowcount = this.mService.spreadsheets().values().get(spreadsheetId, range).execute().getValues().size()
Rather than retrieving all the rows into memory just to get the values in the last row, you can use the append API to append an empty table to the end of the sheet, and then parse the range that comes back in the response. You can then use the index of the last row to request just the data you want.
This example is in Python:
#empty table
table = {
'majorDimension': 'ROWS',
'values': []
}
# append the empty table
request = service.spreadsheets().values().append(
spreadsheetId=SPREADSHEET_ID,
range=RANGE_NAME,
valueInputOption='USER_ENTERED',
insertDataOption='INSERT_ROWS',
body=table)
result = request.execute()
# get last row index
p = re.compile('^.*![A-Z]+\d+:[A-Z]+(\d+)$')
match = p.match(result['tableRange'])
lastrow = match.group(1)
# lookup the data on the last row
result = service.spreadsheets().values().get(
spreadsheetId=SPREADSHEET_ID,
range=f'Sheetname!A{lastrow}:ZZ{lastrow}'
).execute()
print(result)
😢 Google Sheets API v4 does not have a response that help you to get the index of the last written row in a sheet (row that all cells below it are empty). Sadly, you'll have to workaround and fetch all sheet rows' into memory (I urge you to comment if I'm mistaken)
Example:
spreadsheet_id = '1TfWKWaWypbq7wc4gbe2eavRBjzuOcpAD028CH4esgKw'
range = 'Sheet1!A:Z'
rows = service.spreadsheets().values().get(spreadsheetId=spreadsheet_id, range=range).execute().get('values', [])
last_row = rows[-1] if rows else None
last_row_id = len(rows)
print(last_row_id, last_row)
Output:
13 ['this', 'is ', 'my', 'last', 'row']
💡 If you wish to append more rows to the last row, see this
You don't need to. Set a huge range (for example A2:D5000) to guarantee that all your rows will be located in it. I don't know if it has some further impact, may be increased memory consumption or something, but for now it's OK.
private List<String> getDataFromApi() throws IOException {
String spreadsheetId = "1BxiMVs0XRA5nFMdKvBdBZjgmUUqptlbs74OgvE2upms";
String range = "A2:D5000";
List<String> results = new ArrayList<String>();
ValueRange response = this.mService.spreadsheets().values()
.get(spreadsheetId, range)
.execute();
List<List<Object>> values = response.getValues();
if (values != null) {
results.add("Name, Major");
for (List row : values) {
results.add(row.get(0) + ", " + row.get(3));
}
}
return results;
}
Look at the loop for (List row : values). If you have two rows in your table you will get two elements in values list.
Have a cell somewhere that doesn't interfere with your datarange with =COUNTA(A:A) formula and get that value.
In your case
=MAX(COUNTA(A:A50),COUNTA(B:B50))
?
If there could be empty cells inbetween the formula would be a little more tricky but I believe it saves you some memories.
2022 Update
I I don’t know if this will be relevant for someone in 2022, but now you can do it differently.
You can just set next value as range :
const column = "A"
const startIndex = 2
const range = column + startIndex + ":" + column
In resolve you get all data in column and range with last index.
I tested it on js and php
Following Mark B's answer, I created a function that performs a dummy append and then extracts the last row info from the dummy append's response.
def get_last_row_with_data(service, value_input_option="USER_ENTERED"):
last_row_with_data = '1'
try:
dummy_request_append = service.spreadsheets().values().append(
spreadsheetId='<spreadsheet id>',
range="{0}!A:{1}".format('Tab Name', 'ZZZ'),
valueInputOption='USER_ENTERED',
includeValuesInResponse=True,
responseValueRenderOption='UNFORMATTED_VALUE',
body={
"values": [['']]
}
).execute()
a1_range = dummy_request_append.get('updates', {}).get('updatedRange', 'dummy_tab!a1')
bottom_right_range = a1_range.split('!')[1]
number_chars = [i for i in list(bottom_right_range) if i.isdigit()]
last_row_with_data = ''.join(number_chars)
except Exception as e:
last_row_with_data = '1'
return last_row_with_data

Most efficient way of comparing long arrays of strings

I'm using the speech recognizer to get a voice input from the user, it returns an array of 5 strings which I pass to this method
public int analyzeTag(ArrayList<String> voiceResults,Editor editor, Context context){
for (String match : voiceResults) {
Log.d(TAG, match);
if (match.equalsIgnoreCase(context.getResources().getString(R.string.first_tag))){
editor.append(context.getResources().getString(R.string.first_tag));
return 1;
}
else if (match.equalsIgnoreCase(context.getResources().getString(R.string.second_tag))){
editor.append(context.getResources().getString(R.string.second_tag));
return 1;
}
//etc....(huge list of tags)
//Some tags might also have acceptable variations, example:
else if (match.equalsIgnoreCase("img") || match.equalsIgnoreCase("image")
{
editor.append("img"); //the string to append is always taken from the first variation
}
}
return 0;
}
This method compares the results with a list of tags, the tag list will be pretty big with hundreds of tags so I would like to find the most efficient way to do this operation.
I need help with:
1.Is my way of comparing results the most efficient? Is there a better way? (from the user experience perspective, I don't want users waiting a long time to get a result).
The voice input will be a big part of my app so this method will be called quite often
2.I have a long list of tags, obviously the if(), elseIf() route is gonna be quite repetitive, is there a way to iterate this? Considering the fact that some tags might have variations (even more than 1)and that the variation 1 ("img") will be the same for everyone, but other variations will be locale/language sensitive example: "image" for english users "immagini" for italian users etc.
Text appended to the editor will be always taken from the first variation
How about puting tags in a StringArray and then iterate though the array ?
String[] tags = context.getResources().getStringArray(R.array.tags);
for (String match : voiceResults) {
for (int index = 0; index < tags.length; index++ ) {
if (match.equalsIgnoreCase(tags[index]) {
editor.append(tags[index]);
}
}
}
Here's the doc on StringArray

Removing newline from string

Here's my issue:
I have a database and it is full of episodes of a tv show. One column denotes the episode number. I want to display the episodes in a list like this:
Episode 1
Episode 2
Episode 3
etc.
I'm using my own adapter class that extends SimpleCursorAdapter to do this...
Since I had formatting errors I am using Android.R.layout.simple_list_item_1 and Android.R.id.text1
Basically the only reason I have a custom adapter is so I can do something like this:
textView.setText("Episode " + cursor.getString("column_for_episode_number");
The problem is, I get a list that looks like this:
Episode
1
Episode
2
Episode
3
When I try something like this(which worked in a different portion of my code):
String text = "Episode " + cursor.getString("blah");
text = text.replaceAll("\\n","");
I get the exact same list output :(
Why don't I use create a custom view with two textboxes next to each other? It is hard for me to get that to look pretty :/
text.replaceAll(System.getProperty("line.separator"), "");
There is a mistake in your code. Use "\n" instead of "\\n"
String myString = "a string\n with new line"
myString = myString.replaceAll("\n","");
Log.d("myString",myString);
Check if there is new line at the beginning before you replace and do the same test again:
for(int i=0; cursor.getString("blah").length()-1; i++)
{
if(cursor.getString("blah").charAt(i)=='\\n') <-- use the constant for the line separator
{
Log.i("NEW LINE?", "YES, WE HAVE");
}
}
Or use the .contains("\n"); method:
Check the xml for the width of the textview as well.
Why are you using getString() when you are fetching an integer? Use getInt() and then use Integer.toString(theint) when you are setting the values in a textview.
This could help you:
response = response.replaceAll("\\s+","");
It sounds like you are hitting wrapping issues rather than newline issues. Change this:
String text = "Episode " + cursor.getString("blah");
To this:
String text = "Episode" + cursor.getString("blah");
And see if that changes the output. Post your layout xml please?
this worked for my (on android 4.4):
(where body is a string with a newline entered from an EditText view on handset)
for (int i=0; i<body.length(); i++) {
if (body.charAt(i) == '\n' || body.charAt(i) == '\t') {
body = body.substring(0, i) + " " + body.substring(i+1, body.length());
}
}
have you tried
cursor.getString("blah").trim()

Categories

Resources