0

This JSONAray:

"cows": [
    {
      "age": 972,
      "name": "Betty"
      "status": "publish",
      "sticky": "pregnant"
    },
    {
      "age": 977,
      "name"; "Kate"
      "status": "publish",
      "sticky": "heat"
    },
    {
      "age": 959,
      "name": "Julie"
      "site_age": 63178480,
      "sticky": "Nursing"
    },
    ...
 }

that contains 20 objects. What I wanted is this: get 3 random objects out of the 20. And the ages of any of the three won't be a certain number say 961.

Currently this what I am doing:

private void parseCowsReq(JSONObject array) {
         try {
             for (int i = 0; i < 3; i++) {
                 int randumNum = getRandomCow(array);
                 JSONObject jsonObject = array.getJSONObject(randumNum);
                 String cowName = jsonObject.getString("name");
                 String cowStatus = jsonObject.getString("status");
                 Log.d(TAG, "Cow name is " + cowName + "cow Status is " + cowStatus);
             }

         } catch (JSONException e) {
             e.printStackTrace();
         }
  }

  private int getRandomCow(JSONArray jsonArray) {
          int length = jsonArray.length();
          int[] array;
          array = new int[length-1];
          int rnd = new Random().nextInt(array.length);
          return array[rnd];
  }

There are of issues with this code.

  1. I don't know how to ensure that the object gotten in line JSONObject jsonObject = array.getJSONObject(randumNum); won't have an age of 961
  2. The random number gotten is always 0

    Please do you have any idea how this can be done?

1
  • Can't you do it in reverse. i.e find the objects that won't have age as 961. Create a list or array of those filtered elements and then select 3 random objects based on the length of the array or the list? Commented Oct 21, 2016 at 17:14

3 Answers 3

4

you can do it with this:

public ArrayList<Integer> getRandomObject(JSONArray jsonArray, int indexesWeeNeed){
    Random rn = new Random();
    Set<Integer> generated = new LinkedHashSet<>();
    while(generated.size() < indexesWeeNeed){
        int index = rn.nextInt(10);
        JSONObject jsonObject = (JSONObject) jsonArray.get(index);
        int age = jsonObject.getInt("age");
        if(age<961) {
            generated.add(index);
        }
    }
    ArrayList<Integer> arrayList = new ArrayList<>();
    arrayList.addAll(generated);
    return arrayList;
}
Sign up to request clarification or add additional context in comments.

7 Comments

Thanks. In line randomNum = I; you actually meanString randomNum = i; , right? If yes, the result gave me -14 which printed this org.json.JSONException: Index -14 out of range [0..20) in logcat.
There one final problem, if the random number is 20, it throws a JSONException. In JSONArray, the array starts from 0. So in this case there'll be no 20th item rather there are 0-19 items. However in line int randomNum = rn.nextInt(jsonArray.length + 1); I changed + to - and I've gotten no problems. But what do you think about this?
Sorry I mistakenly posted an unfinished comment. It's complete now.
no don't do that just use the one I posted. delete +1 @Ozuf
ok. But that might return a number that is 20, right? And another thing, it returned a the same number twice. Sorry for bugging you pls.
|
0

One part that's messed up is when you call
Random().nextInt(array.length);
array.length is the new array you just created. You need to perform the function on the existing array:
Random().nextInt(jsonArray)
to get a random number other than zero.

As for ensuring you don't get a certain age, I'd suggest breaking up the code to not call the getRandomCow(array) function inside of the for loop. When you retrieve a cow, check the name doesn't match, check the age, and if it works, keep it. If not get another cow.

Comments

0

Well firstly, load the objects:

JSONArray array = /* your array */;

Next, we need a method to retrieve 3 unique objects from the JSONArray (which is actually a List). Let's shuffle the indexes of the json array, so that we don't end up having to repeatedly generate duplicates:

public Stream<JSONObject> randomObjects(JSONArray array, int amount) {
    if (amount > array.size()) {
        //error out, null, return array, whatever you desire
        return array;
    }
    List<Integer> indexes = IntStream.range(0, array.size()).collect(Collectors.toList());
    //random, but less time generating them and keeping track of duplicates
    Collections.shuffle(indexes);
    Set<Integer> back = new HashSet<>();
    Iterator<Integer> itr = indexes.iterator();
    while (back.size() < amount && itr.hasNext()) {
        int val = itr.next();
        if (array.get(val).getInt("age") != 961) { //or any other predicates
            back.add(val);
        }
    }
    return back.stream().map(array::get);
}

Using this, we can select the three objects from the list and utilize them how we wish:

randomObjects(array, 3).map(o -> o.getInt("age")).forEach(System.out::println);
//972
//977
//952

When I said "or any other predicates, you can pass those as well via the method:

public Stream<JSONObject> randomObjects(..., Predicate<Integer> validObject) {
    //...
    int val = itr.next();
    if (validObject.test(val)) {
        back.add(val);
    }
    //...
}

Which would mean you could change the blacklisting per method call:

Stream<JSONObject> random = randomObjects(array, 3, val -> array.get(val).getInt("age") != 961);

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.