Categories
discuss

How to get the array index in Lodash _.each

I’m newbie in JavaScript. I have a question

My code in Java:

public void checkArray(int a, int b) {
    int[]days = new int[]{5, 15, 25};
    int[]hours = new int[]{6, 8, 7};
    ArrayList<Interger> result = new ArrayList<>();
    for (int i = 0; i < days.length-1;  i++) {
        if (days[i] < a && b < days[i+1]) {
            result.add(hours[i]);
        } else if (days[i] > a && days[i] < b) {
            result.add(hours[i]);
            if (i > 0) {
                result.add(hours[i-1]);
            }
        }

How can I write this code in JavaScript with Lodash _.each? I can’t find a variable like [i] in JavaScript code, so I can’t check the condition [if (days[i] < a && b < days[i+1])]

My code in JavaScript:

_.each(days, day => {
    //TODO something
})

Answer

From the Lodash documentation:

Iterates over elements of collection and invokes iteratee for each element. The iteratee is invoked with three arguments: (value, index|key, collection). Iteratee functions may exit iteration early by explicitly returning false.

This means that you can simply do:

_.each( days, function( day, i ){

});

So your whole code becomes:

var days = [5, 15, 25];
var hours = [6, 8, 7];
var result = [];

_.each( days, function( day, i ){
    if( days[i] < a && b < days[i+1] ){ // days[i] == day
        result.push( hours[i] );
    } else if( days[i] > a && days[i] < b ){
        result.push( hours[i] );
        if( i > 0 ){
            result.push( hours[i-1] );
        }
    }
})

Here is a jsFiddle to experiment.

Categories
discuss

Android Studio CMake/Ninja Not Used for Building an NDK project

I have the following CMAKE & Ninja installed through Android Studio’s SDK Tools:

~/Library/Android/sdk/cmake/3.10.2.4988404/bin/ninja --version
1.8.2

I run into “Error Configuring” while trying to build my project. Here is the build output:

Executable : /Users/ssk/Library/Android/sdk/cmake/3.10.2.4988404/bin/cmake
arguments : 
-H/Users/ssk/MyProject
-B/Users/ssk/MyProject/.externalNativeBuild/cmake/debug/armeabi-v7a
-DANDROID_ABI=armeabi-v7a
-DANDROID_PLATFORM=android-16
-DCMAKE_LIBRARY_OUTPUT_DIRECTORY=/Users/ssk/MyProject/build/intermediates/cmake/debug/obj/armeabi-v7a
-DCMAKE_BUILD_TYPE=Debug
-DANDROID_NDK=/Users/ssk/Library/Android/sdk/ndk-bundle
-DCMAKE_CXX_FLAGS=-std=c++11
-DCMAKE_SYSTEM_NAME=Android
-DCMAKE_ANDROID_ARCH_ABI=armeabi-v7a
-DCMAKE_SYSTEM_VERSION=16
-DCMAKE_EXPORT_COMPILE_COMMANDS=ON
-DCMAKE_ANDROID_NDK=/Users/ssk/Library/Android/sdk/ndk-bundle
-DCMAKE_TOOLCHAIN_FILE=/Users/ssk/Library/Android/sdk/ndk-bundle/build/cmake/android.toolchain.cmake
-G Ninja
-DANDROID_STL=gnustl_statics
-DANDROID_CPP_FEATURES=rtti exception
-DANDROID_TOOLCHAIN=gcc
-DANDROID_NDK=/Users/ssk/android-ndk-r17c/
jvmArgs : 

It’s missing:

-DCMAKE_MAKE_PROGRAM=/Users/ssk/Library/Android/sdk/cmake/3.10.2.4988404/bin/ninja

Error:

 CMake was unable to find a build program corresponding to "Ninja".  CMAKE_MAKE_PROGRAM is not set.  You probably need to select a different build tool

Only if I switch to CMake version say 3.6.3155560 it works. Otherwise, I have to install ninja from brew or macports.

Here is the snippet from my build.gradle:

 externalNativeBuild {
        cmake {
            // Linker flags and Visibility options keeps the size of the library small
            cppFlags "-std=c++11"
            arguments "-DANDROID_STL=gnustl_static",
                      "-DANDROID_CPP_FEATURES=rtti exceptions",
                      "-DANDROID_TOOLCHAIN=gcc"
        }
    }

How to fix it?

Answer

Install/Update CMake From Android Studio SDK Manager

Install/Update CMake From Android Studio SDK Manager

Check your CMake from sdk root directory if ninja exists. enter image description here


Below is not good.

cmake {
    cppFlags "-std=c++11"
    arguments "-DANDROID_ABI=armeabi-v7a",
                "-DANDROID_PLATFORM=android-16",
                "-DANDROID_STL=gnustl_static",
                "-DANDROID_CPP_FEATURES=rtti exceptions",
                "-DCMAKE_LIBRARY_OUTPUT_DIRECTORY=libs"
}

Because, ANDROID_PLATFORM should be automatically decided by Android external native build system according to minSdkVersion, see below official document from how ANDROID_PLATFORM works:

Instead of changing this flag directly, you should set the minSdkVersion property in the defaultConfig or productFlavors blocks of your module-level build.gradle file. This makes sure your library is used only by apps installed on devices running an adequate version of Android. The CMake toolchain then chooses the best platform version for the ABI you’re building using the following logic:

  1. If there exists a platform version for the ABI equal to minSdkVersion, CMake uses that version. Otherwise,
  2. if there exists platform versions lower than minSdkVersion for the ABI, CMake uses the highest of those platform versions. This is a reasonable choice because a missing platform version typically means that there were no changes to the native platform APIs since the previous available version.
  3. Otherwise, CMake uses the next available platform version higher than minSdkVersion.

And, -DANDROID_ABI=armeabi-v7a is not good as well. You should not define this parameter here. CMake will iterate all your ABIs according to your abiFilters automatically. If you just want to build armeabi-v7a, you can specify this using abiFilter, e.g.

externalNativeBuild {
    cmake {
        abiFilters 'armeabi-v7a', 'arm64-v8a'
    }
}

Also, rtti and exceptions are cppFlags, below should be the proper way to set these two flags.

cppFlags "-std=c++11 -frtti -fexceptions"

Ensure that your have properly configured ANDROID_NDK path, because according to your question, you have TWO version of NDK set, one is -DANDROID_NDK=/Users/ssk/android-ndk-r17c/, the other one is -DANDROID_NDK=/Users/ssk/Library/Android/sdk/ndk-bundle. Config NDK path from local.properties:

ndk.dir=/Users/ssk/Library/Android/sdk/ndk-bundle
sdk.dir=/Users/ssk/Library/Android/sdk

what is the fix for -GAndroid Gradle – Ninja?

Add below arguments to the cmake config:

externalNativeBuild { 
    cmake { 
        ...
        version "3.10.2"
        arguments "-GAndroid Gradle - Ninja"
    } 
} 
Categories
discuss

Add callback function to Java stream

Let’s say I want to perform the following operations:

  • List the files in a given directory (as a stream)
  • Map each file (Path) into a Reader (BufferedReader for example) for a consumer to consume.
  • Once a file has been consumed, delete the files

The code would look a bit like this:

Stream<Reader> stream = Files.list(Paths.get("myFolder")) // Returns a stream of Path
  .callback(Files::delete)                                // This would have to be called after the reader has been consumed
  .map(Files::newBufferedReader);                         // Maps every path into a Reader

If I use peek() to delete the files, then the file won’t be there when it needs to be mapped into a Reader, so I’d need something that runs after the stream is consumed. Any idea?

Answer

I went for a slightly different approach in the end. I extended the Reader class and created a wrapper, and I simply overrode the close() method to perform some additional operations on the file (i.e. rename, delete, move etc) once the reader has been consumed.

public class CustomReader extends Reader {
  private Reader reader;
  private File file;

  public CustomReader(File file) {
    this.file = file;
    this.reader = new FileReader(file);
  } 

  [...]
  @Override
  public void close() {
    super.close();
    // Do what you need to do with your file
  }
}
Categories
discuss

What causes this behavioural difference between C and JavaScript?

Given the C code below:

int nSum       = 0;
// pNumber is 9109190866037
int nDigits    = strlen(pNumber);
int nParity    = (nDigits-1) % 2;
char cDigit[2] = "";
for (int i = nDigits; i > 0 ; i--)
{
  cDigit[0]  = pNumber[i-1];
  int nDigit = atoi(cDigit);

  if (nParity == i % 2) {
    nDigit = nDigit * 2;
  }

  nSum += nDigit/10;
  nSum += nDigit%10;
  printf("NUMBER: %dn", nSum);
}

Outputs:

NUMBER: 13
NUMBER: 13
NUMBER: 16
NUMBER: 22
NUMBER: 29
NUMBER: 29
NUMBER: 38
NUMBER: 39
NUMBER: 48
NUMBER: 48
NUMBER: 50
NUMBER: 59
NUMBER: 59

And this JavaScript code (written in TypeScript, so there actually is typing involved here as well, but it is mostly inferred):

let nSum = 0;
let nDigits = partialIdNumber.length;
let nParity = (nDigits - 1) % 2;
let cDigit = "";
for (let i = nDigits; i > 0; i--) {

  cDigit = partialIdNumber[i - 1];
  let nDigit = parseInt(cDigit);

  if (nParity == i % 2) {
    nDigit  = nDigit * 2;
  }
  nSum += nDigit / 10;
  nSum += nDigit % 10;
  console.log("NUMBER: %d", nSum);
}

Outputs:

NUMBER: 14.3
NUMBER: 14.3
NUMBER: 17.5
NUMBER: 24.1
NUMBER: 31.700000000000003
NUMBER: 31.700000000000003
NUMBER: 41.5
NUMBER: 42.6
NUMBER: 52.4
NUMBER: 52.4
NUMBER: 54.6
NUMBER: 64.5

NOTE: Both these implementations are the same, just different languages.

The C code produces the expected results and JavaScript doesn’t.

Questions

  1. What assumptions does JavaScript make in order to produce that output?
  2. What part of my JavaScript code would I have to change to produce the desired output?

Answer

You need to convert numbers after using division to an integer value.

var partialIdNumber ='9109190866037'

let nSum = 0;
let nDigits = partialIdNumber.length;
let nParity = (nDigits - 1) % 2;
let cDigit = "";
for (let i = nDigits; i > 0; i--) {
    cDigit = partialIdNumber[i - 1];
    let nDigit = +cDigit;
    if (nParity == i % 2) {
        nDigit  = nDigit * 2;
    }
    nSum += Math.floor(nDigit / 10); // int
    nSum += nDigit % 10;
    console.log("NUMEBR: %d", nSum);
}
Categories
discuss

How to transform the context of fragment into a LifecycleOwner?

I have the following scenario. I have an activity which holds a fragment. In this fragment I’m displaying some records from a back-end database. I’m also using an adapter that looks like this:

public class MovieAdapter extends PagedListAdapter<Movie, MovieAdapter.MovieViewHolder> {
    private Context context;

    public MovieAdapter(Context context) {this.context = context;}

    @NonNull
    @Override
    public MovieViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        //Create the view
    }

    @Override
    public void onBindViewHolder(@NonNull final MovieViewHolder holder, int position) {
        Movie movie = getItem(position);
        String title = movie.title;
        holder.titleTextView.setText(title);

        MovieRepository movieRepository = new MovieRepository(context);
        LiveData<Movie> liveData = movieRepository.retrieveFavoriteMovie(movie.id);
        liveData.observe(context, m -> { //Error
            if(m != null) {
                boolean favorite = m.favorite;
                if(favorite) {
                    //Do something
                } else {
                    //Do something else
                }
            }
        });
    }

    class MovieViewHolder extends RecyclerView.ViewHolder {
        ImageView favoriteImageView;
        TextView titleTextView;

        MovieViewHolder(View itemView) {
            super(itemView);
            titleTextView = itemView.findViewById(R.id.title_text_view);                favoriteImageView = itemView.findViewById(R.id.favorite_image_view);
        }
    }
}

In the onBindViewHolder I’m trying to check if a specific movie exist in Romm database but I get this error:

Wrong 1st argument type. Found: 'android.content.Context', required: 'android.arch.lifecycle.LifecycleOwner'

So how to transform the context of fragment into a LifecycleOwner so I can use it as in argument in my method?

Answer

android.content.Context does not implement android.arch.lifecycle.LifecycleOwner.

You’d have to pass an instance of AppCompatActivity, which implements android.arch.lifecycle.LifecycleOwner (or any other class which does that).

or cast (AppCompatActivity) context, when context is an instanceof AppCompatActivity. To get the Activity from the Context in a reliable manner, check https://stackoverflow.com/a/46205896/2413303

Source: stackoverflow
Text is available under the Creative Commons Attribution-ShareAlike License; additional terms may apply. By using this site, you agree to the Privacy Policy, and Copyright Policy. Content is available under CC BY-SA 3.0 unless otherwise noted. The answers/resolutions are collected from stackoverflow, are licensed under cc by-sa 2.5 , cc by-sa 3.0 and cc by-sa 4.0 © No Copyrights, All Questions are retrived from public domain..