I need a little help.
I have a string array (urllinks) which I want to fill with url links which are being parsed with jsoup through a for loop.
In below code example there are 2 urls but the list only gets filled with the first link. I don`t know how many links will be parsed, can be 1 but also 12.
public static String[] urllinks;
...
for (int i = 0; i < links.size(); i++) { // links size = 2
String url = doc.select("a").attr("abs:href");
urllinks[i] = url;
}
Any help would be appreciated.
Thanks in advance.
You problem is due to the fact that you call attr("abs:href") on doc.select("a") which returns an object of type Elements such that you always get the first match as stated in the javadoc:
Get an attribute value from the first matched element that has the
attribute.
You should rather iterate as next:
List<String> urls = new ArrayList<>();
// Iterate over all the links that have an attribute abs:href
for (Element link : doc.select("a[abs:href]")) {
urls.add(link.attr("abs:href"));
}
urllinks = urls.toArray(new String[urls.size()]);
To answer my own question, I solved it by creating an arraylist and then convert it back to a string array.
Dirty but it works.
{
private static String[] urllinks;
private static ArrayList<String> mStringList = new ArrayList<>();
...
int i = 0;
for (Element el : links) {
String url = el.attr("abs:href");
if (url != null) {
mStringList.add(i, url);
i++;
}
else {
// Do something
}
urllinks = mStringList.toArray(urllinks);
// check if urls are actualy in string array
Log.d("LINK 1", urllinks[0]);
Log.d("LINK 2", urllinks[1]);
...
}
Related
I have a java list of URLs. I wish to call a function for each URL in the list. And this function adds URL to the list.
Is it possible to loop over all the URLs including newly added URLs in the list?
for(String links: urls) {
ar = getNews(links);
}
inside getNews() there is:
urls.add(json.optString("next"));
I did this successfully using recursion. By calling:
getNews(json.optString("next"));
inside getNews()
You can use regular for loop and change the condition each iteration
int size = 1;
for (int i = 0 ; i < size ; ++i) {
ar = getNews(urls.get(i));
size = urls.size();
}
Use a Queue instead of a list:
Queue<String> q = new LinkedList<>();
q.add(initial urls);
while (!q.isEmpty()) {
String url = q.pop();
q.addAll(readNews(url));
}
I am assuming that this code lives outside the readNews method, i.e. there is no recursion here.
Also, since I assume this is some sort of crawler, you might want to keep track of URLs you visited previously, to avoid visiting them again:
Queue<String> q = new LinkedList<>();
Set<String> visited = new LinkedHashSet<>();
q.add(initial urls);
while (!q.isEmpty()) {
String url = q.pop();
if (visited.add(url)) {
q.addAll(readNews(url));
}
}
i'm trying to display few elements of an arraylist if contition is true. The method gets String that should be found in arrayList. After that there are some other values that are contained after the line in List that has beed found.
I need to print thause line's out that would be 1_4_1334-Automatic.... I have tried to use Iterator but with no luck. It just seens that i just cannot get it.
So if am looking for 2210002_4_1294-Group i should get all strings that contain "Automatic" till 2210003_4_1295-Group is reached.
Any idea how it could be done ?
Thanks a lot :)
MyArrayList:
2210002_4_1294-Group
1_4_1334-Automatic
2_4_1336-Automatic
3_4_1338-Automatic
4_4_1340-Automatic
5_4_1342-Automatic
6_4_1344-Automatic
7_4_1346-Automatic
8_4_1348-Automatic
9_4_1350-Automatic
2210003_4_1295-Group
1_4_1378-Automatic
2_4_1380-Automatic
2210004_4_1296-Group
1_4_1384-Manual
2_4_1386-Manual
Method might look like this:
private void findValueInList(String group){
Iterator<String> iter = arrayList.iterator();
while(iter.hasNext()){
String name = iter.next();
if(name.equals(group)){
here i need to get ValueThatINeed
}
}
}
I guess your question is already answered Here
Simply iterate over your arraylist and check each value like the code below:
ArrayList<String> myList ...
String searchString = "someValue";
for (String curVal : myList){
if (curVal.contains(searchString)){
// The condition you are looking for is satisfied
}
}
I solved it like this:
private ArrayList<String> filterList(String nameToFind) {
ArrayList<String> elements = new ArrayList<String>();
for (int i = 0; i < list.size(); i++) {
if (list.get(i).equals(nameToFind)) {
while (list.get(i+1).contains("Manual") || list.get(i+1).contains("Automatic")) {
elements.add(list.get(i+1));
i++;
}
}
}
return elements;
}
I am trying to upload files by multi part in android via servlets(server code). So i can iterate the loop like this.
for (Part part : request.getParts()) {
//uploading current part.. working..
}
but i want to iterate like below,
for (int i = 0; i < request.getParts().size(); i++) {
//request.getPart(i); not working..
//request.getPart(i+1); not working..
}
The reason is need current part as well as next part on each and every iteration. Is it possible to do like above or any other ways to do it. How can I achieve this?
HttpServletRequest.getParts() returns a Collection which does not allow index based access as Lists do.
You could first copy all parts into an ArrayList and then loop over that list:
ArrayList<Parts> parts = new ArrayList<>(request.getParts());
for (int i=0; i<parts.size()-1; i+=2) {
// parts.get(i);
// parts.get(i+1);
}
Perhaps this is helping ...
I did it with an for each loop.
Application example:
for (Part part : request.getParts()) {
// Your code. For example:
fileName = getFileName(part);
part.write(fileName);
}
private String getFileName(Part part) {
String contentDisp = part.getHeader("content-disposition");
String[] tokens = contentDisp.split(";");
for (String token : tokens) {
if (token.trim().startsWith("filename")) {
return token.substring(token.indexOf("=") + 2, token.length() - 1);
}
}
return "";
}
I hope it helped!
I have an XML array that I access to pull a random question from. How would I go about making sure there is no duplicates pulled? My current code follows.
private void getQuestion() {
// TODO Auto-generated method stub
res = getResources();
qString = res.getStringArray(R.array.questions);
rQuestion = qString[rgenerator.nextInt(qString.length)];
tokens = new StringTokenizer(rQuestion, ":");
wordCount = tokens.countTokens();
sep = new String[wordCount];
wArray = 0;
while (tokens.hasMoreTokens()) {
sep[wArray] = tokens.nextToken();
wArray++;
}
}
Any help would be appreciated.
The Fisher-Yates shuffle is an algorithm that is more or less designed for this purpose.
You are better off putting that array of questions in a list and use Collections.shuffle(). After that, simply iterate through the list. More information can be found at this related answer.
This solution will cost some memory for duplicating the list, but remember that the strings themselves won't be copied, only the references to the questions are. For maximum performance, use a list with random access (ArrayList), or use that as a replacement for the array. If you don't theshuffle method will create one internally.
If you want a fast way of getting only unique values from an array this link has a very fast method. Below uses an ArrayList, but it will not be hard for you to convert from string array to an ArrayList - or just use ArrayLists instead.
e.g. new ArrayList(Arrays.asList(myArray));
In short you use a hashset to only get unique values using this method
public static ArrayList GetUniqueValues(Collection values)
{
return new ArrayList(new HashSet(values));
}
Then use it like so
ArrayList x = new ArrayList();
x.add("abc");
x.add("abc");
x.add("abc");
x.add("def");
x.add("def");
x.add("ghi");
for (Object y : GetUniqueValues(x))
Log.d("something", y); //ok lets print the value
To yield the result of "abc, def, and ghi"
To be clear I agree with Travis to ask why you have duplicates. The above is to answer the question.
I figured it out. I switched it to
private void getQuestion() {
res = getResources();
qString = res.getStringArray(R.array.questions);
arrayLength = qString.length;
qTotal = arrayLength;
}
private void getRandom() {
rnd = rgenerator.nextInt(arrayLength);
rQuestion = qString[rnd];
qString[rnd] = "used";
seperate();
}
private void seperate() {
if (rQuestion != "used") {
tokens = new StringTokenizer(rQuestion, ":");
wordCount = tokens.countTokens();
sep = new String[wordCount];
wArray = 0;
while (tokens.hasMoreTokens()) {
sep[wArray] = tokens.nextToken();
wArray++;
}
qNumber++;
} else {
if (qNumber < qTotal) {
getRandom();
} else {
startActivity(new Intent("com.example.END"));
}
}
}
It gets the array from resources, then pulls a random question from the array. It then sets that one to "used" and splits it. It also checks to see if the pulled question is "used, and if it is, it pulls another question. It also goes to the end game activity if all questions are "used"
How do I get the values in a piece of Html (values="valueIWant"), and have them in an Array ?
I tried the following, but that didn't work:
HttpEntity entity5 = response5.getEntity();
String defaultString = EntityUtils.toString(entity5);
Document defaultDoc = Jsoup.parse(defaultString);
Elements values = defaultDoc.getElementsByAttribute("value"); //DropDownList Values
String s[] = {""};
for(int a=0; a<values.size(); a++){
s[a] = values.get(a).toString();
}
return s;
So anyone got an answer? thanks. (Btw, i use Jsoup)
First of all: is your HTML parsed correctly? Can you provide the contents of defaultString? Is defaultDoc valid is there a problem with file encodings perhaps?
Assuming getElementsByAttribute actually returns some objects —note that you have a typo, value instead of values— you're currently populating the array with the descriptions of all Element-objects, not the values of the attribute. Try something like the following:
int i = 0;
String s[] = new String[values.size()];
for(Element el : values){
s[i++] = el.attr("values");
}