问:
Issue with image orientation when capturing using camera2 api in android version 10
I have been updated my camera feature from Camera to camera2 api.

When i capture the image with front camera and display it in imageview. the orientation of the image is changed. Then i used this code to change the orientation of the image.

```<code>int jpegOrientation =
                (ORIENTATIONS.get(rotation) + characteristics.get(CameraCharacteristics.SENSOR_ORIENTATION) + 270) % 360;
capturebuilder.set(CaptureRequest.JPEG_ORIENTATION, jpegOrientation);
</code>```

Above code is working for android version(i.e version 5,9) which i have tested. When i run the same code in Android version 10 it does not work. Below is the image

please,any one can help me out for this issue

答:
```<code>private int getJpegOrientation(CameraCharacteristics c, int deviceOrientation) {
     if (deviceOrientation == android.view.OrientationEventListener.ORIENTATION_UNKNOWN) return 0;
     int sensorOrientation = c.get(CameraCharacteristics.SENSOR_ORIENTATION);

     // Round device orientation to a multiple of 90
     deviceOrientation = (deviceOrientation + 45) / 90 * 90;

     // Reverse device orientation for front-facing cameras
     boolean facingFront = c.get(CameraCharacteristics.LENS_FACING) == CameraCharacteristics.LENS_FACING_FRONT;
     if (facingFront) deviceOrientation = -deviceOrientation;

     // Calculate desired JPEG orientation relative to camera orientation to make
     // the image upright relative to the device orientation
     int jpegOrientation = (sensorOrientation + deviceOrientation + 360) % 360;

     return jpegOrientation;
 }
</code>```

to know more details follow this post: https://medium.com/@kenodoggy/solving-image-rotation-on-android-using-camera2-api-7b3ed3518ab6

Body:
I have been updated my camera feature from Camera to camera2 api.

When i capture the image with front camera and display it in imageview. the orientation of the image is changed. Then i used this code to change the orientation of the image.

int jpegOrientation =
                (ORIENTATIONS.get(rotation) + characteristics.get(CameraCharacteristics.SENSOR_ORIENTATION) + 270) % 360;
capturebuilder.set(CaptureRequest.JPEG_ORIENTATION, jpegOrientation);

Above code is working for android version(i.e version 5,9) which i have tested. When i run the same code in Android version 10 it does not work. Below is the image

please,any one can help me out for this issue

Body:
private int getJpegOrientation(CameraCharacteristics c, int deviceOrientation) {
     if (deviceOrientation == android.view.OrientationEventListener.ORIENTATION_UNKNOWN) return 0;
     int sensorOrientation = c.get(CameraCharacteristics.SENSOR_ORIENTATION);

     // Round device orientation to a multiple of 90
     deviceOrientation = (deviceOrientation + 45) / 90 * 90;

     // Reverse device orientation for front-facing cameras
     boolean facingFront = c.get(CameraCharacteristics.LENS_FACING) == CameraCharacteristics.LENS_FACING_FRONT;
     if (facingFront) deviceOrientation = -deviceOrientation;

     // Calculate desired JPEG orientation relative to camera orientation to make
     // the image upright relative to the device orientation
     int jpegOrientation = (sensorOrientation + deviceOrientation + 360) % 360;

     return jpegOrientation;
 }

to know more details follow this post: https://medium.com/@kenodoggy/solving-image-rotation-on-android-using-camera2-api-7b3ed3518ab6


来源: stackexchange

问:
Selenium "No module named 'selenium' " even after pip3 install
I do not know why I cannot import selenium even after I pip install it.
Does anyone know how else I can troubleshoot it or how to fix this?

I am using Mac OS and python 3.7.4

```<code>python3
Python 3.7.4

Type "help", "copyright", "credits" or "license" for more information.
>>> import selenium
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ModuleNotFoundError: No module named 'selenium'
>>>
pip3 install selenium
Requirement already satisfied: selenium in /usr/local/lib/python3.7/site-packages
Requirement already satisfied: urllib3 in /usr/local/lib/python3.7/site-packages (from selenium)
</code>```

UPDATE

I was kind of messing around and one of the things that I did helped make it work. I am not sure which of the items but if someone can explain it so I understand this in the future, that would be appreciated.

I did brew doctor which outputted the following

```<code>Please note that these warnings are just used to help the Homebrew maintainers
with debugging if you file an issue. If everything you use Homebrew for is
working fine: please don't worry or file an issue; just ignore this. Thanks!

Warning: A newer Command Line Tools release is available.
Update them from Software Update in System Preferences or
https://developer.apple.com/download/more/.

Warning: You have unlinked kegs in your Cellar.
Leaving kegs unlinked can lead to build-trouble and cause brews that depend on
those kegs to fail to run properly once built. Run `brew link` on these:
  python
</code>```

brew link --overwrite python

vi /usr/local/bin/pip
and changed /usr/local/opt/python/bin/python3.7 to /usr/local/opt/python/bin/python3 and it worked
I am guessing my issue is that I have two instances of python installed so it was downloading the selenium library to a difference python version (3.7) instead of 3 which is what I wanted.

Let me know if you think this was the issue or if you can clarify what you may think is the issue

答:
Please check the pip version using command

```<code>pip --version
</code>```

Mostly, pip is associated with python version 2.7 while pip3 is associated with python3

So, try -

```<code>pip3 install selenium
</code>```

Since pip will install it for python2 while pip3 will install for python3 as you are using python3 in the question.

ContentLicense: CC BY-SA 4.0

Body:
I do not know why I cannot import selenium even after I pip install it.
Does anyone know how else I can troubleshoot it or how to fix this?

I am using Mac OS and python 3.7.4

python3
Python 3.7.4

Type "help", "copyright", "credits" or "license" for more information.
>>> import selenium
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ModuleNotFoundError: No module named 'selenium'
>>>
pip3 install selenium
Requirement already satisfied: selenium in /usr/local/lib/python3.7/site-packages
Requirement already satisfied: urllib3 in /usr/local/lib/python3.7/site-packages (from selenium)

UPDATE

I was kind of messing around and one of the things that I did helped make it work. I am not sure which of the items but if someone can explain it so I understand this in the future, that would be appreciated.

I did brew doctor which outputted the following

Please note that these warnings are just used to help the Homebrew maintainers
with debugging if you file an issue. If everything you use Homebrew for is
working fine: please don't worry or file an issue; just ignore this. Thanks!

Warning: A newer Command Line Tools release is available.
Update them from Software Update in System Preferences or
https://developer.apple.com/download/more/.

Warning: You have unlinked kegs in your Cellar.
Leaving kegs unlinked can lead to build-trouble and cause brews that depend on
those kegs to fail to run properly once built. Run `brew link` on these:
  python

brew link --overwrite python

vi /usr/local/bin/pip
and changed /usr/local/opt/python/bin/python3.7 to /usr/local/opt/python/bin/python3 and it worked
I am guessing my issue is that I have two instances of python installed so it was downloading the selenium library to a difference python version (3.7) instead of 3 which is what I wanted.

Let me know if you think this was the issue or if you can clarify what you may think is the issue

Body:
Please check the pip version using command

pip --version

Mostly, pip is associated with python version 2.7 while pip3 is associated with python3

So, try -

pip3 install selenium

Since pip will install it for python2 while pip3 will install for python3 as you are using python3 in the question.


答: try pip install, instead of pip3</p>

Title: Selenium "No module named 'selenium' " even after pip3 install

Body: try pip install, instead of pip3


问:
Best option for merging multiple files within the same partition in hadoop?
I have a table partitioned on event_date, and for some reason, when I inserted data into my external table, some dates have only one or two files, while some have over 200.

I always use this snippet of code when kicking off the Hive queries to insert the data, so I'm not sure where/how it went out of whack for some dates, but not others. I thought the 'merge.tezfiles' line specifically is what handled the file merging upon insert.

```<code>SET mapred.job.queue.name=my_directory;
use this_directory;
SET hive.exec.dynamic.partition=true;
SET hive.exec.dynamic.partition.mode=nonstrict;
SET hive.exec.max.dynamic.partitions=2000;
SET hive.exec.max.dynamic.partitions.pernode=2000;
SET hive.merge.tezfiles=true;
</code>```

Everything I've found online mentions having to copy the files locally and uploading them again.

Is there a way to merge the multiple files within each date partition in a clean and simple way?

I have tried the following on a few dates which had 4 and 15 files, respectively. The Hive output after it ran confirmed that the extraneous files had been deleted, but when I went back and looked in Hadoop, there were just as many as when I started. Luckily the data was still accurate when I checked it, so I'm not sure what it deleted in the first place? Is this not at all the right command to be using?

```<code>alter table table_being_edited PARTITION(event_dt='2017-01-01') CONCATENATE;
</code>```

Here is one such line where it confirmed the extra files had been removed:

```<code>Moved: 'my_hdfs_filepath/event_dt=2019-10-24/000052_0' to trash at: my_trash_directory/.Trash/Current
</code>```

OK
Time taken: 75.321 seconds

For the date that had 15 files, it gave me a similar output 15x.

I'm hoping to narrow down the dates with many files down to just one or two if at all possible, as we are running out of namespace. I'm very new to all of this, so is there any barebones, simple way of merging files within a single date partition?

答:
If your block size of HDFS/MapR-FS is 256MB, it is better to set the smallfiles.avgsize to 256MB</p>

```<code>SET hive.merge.tezfiles=true; --Merge small files at the end of a Tez DAG.
SET hive.merge.mapfiles=true; --Hive will start an additional map-reduce job to merge the output files into bigger files
SET hive.merge.mapredfiles=true; --Hive will start an additional map-reduce job to merge the output files into bigger files
SET hive.merge.orcfile.stripe.level=true; --When hive.merge.mapfiles, hive.merge.mapredfiles or hive.merge.tezfiles is enabled while writing a table with ORC file format, enabling this configuration property will do stripe-level fast merge for small ORC files.
SET hive.merge.size.per.task=256000000; --Size of merged files at the end of the job.
SET hive.merge.smallfiles.avgsize=256000000; --When the average output file size of a job is less than this number, Hive will start an additional map-reduce job to merge the output files into bigger files. This is only done for map-only jobs if hive.merge.mapfiles is true, and for map-reduce jobs if hive.merge.mapredfiles is true.
</code>```

Body:
I have a table partitioned on event_date, and for some reason, when I inserted data into my external table, some dates have only one or two files, while some have over 200.

I always use this snippet of code when kicking off the Hive queries to insert the data, so I'm not sure where/how it went out of whack for some dates, but not others. I thought the 'merge.tezfiles' line specifically is what handled the file merging upon insert.

SET mapred.job.queue.name=my_directory;
use this_directory;
SET hive.exec.dynamic.partition=true;
SET hive.exec.dynamic.partition.mode=nonstrict;
SET hive.exec.max.dynamic.partitions=2000;
SET hive.exec.max.dynamic.partitions.pernode=2000;
SET hive.merge.tezfiles=true;

Everything I've found online mentions having to copy the files locally and uploading them again.

Is there a way to merge the multiple files within each date partition in a clean and simple way?

I have tried the following on a few dates which had 4 and 15 files, respectively. The Hive output after it ran confirmed that the extraneous files had been deleted, but when I went back and looked in Hadoop, there were just as many as when I started. Luckily the data was still accurate when I checked it, so I'm not sure what it deleted in the first place? Is this not at all the right command to be using?

alter table table_being_edited PARTITION(event_dt='2017-01-01') CONCATENATE;

Here is one such line where it confirmed the extra files had been removed:

Moved: 'my_hdfs_filepath/event_dt=2019-10-24/000052_0' to trash at: my_trash_directory/.Trash/Current

OK
Time taken: 75.321 seconds

For the date that had 15 files, it gave me a similar output 15x.

I'm hoping to narrow down the dates with many files down to just one or two if at all possible, as we are running out of namespace. I'm very new to all of this, so is there any barebones, simple way of merging files within a single date partition?

Body:
If your block size of HDFS/MapR-FS is 256MB, it is better to set the smallfiles.avgsize to 256MB

SET hive.merge.tezfiles=true; --Merge small files at the end of a Tez DAG.
SET hive.merge.mapfiles=true; --Hive will start an additional map-reduce job to merge the output files into bigger files
SET hive.merge.mapredfiles=true; --Hive will start an additional map-reduce job to merge the output files into bigger files
SET hive.merge.orcfile.stripe.level=true; --When hive.merge.mapfiles, hive.merge.mapredfiles or hive.merge.tezfiles is enabled while writing a table with ORC file format, enabling this configuration property will do stripe-level fast merge for small ORC files.
SET hive.merge.size.per.task=256000000; --Size of merged files at the end of the job.
SET hive.merge.smallfiles.avgsize=256000000; --When the average output file size of a job is less than this number, Hive will start an additional map-reduce job to merge the output files into bigger files. This is only done for map-only jobs if hive.merge.mapfiles is true, and for map-reduce jobs if hive.merge.mapredfiles is true.


问:
Best approach to make a fullscreen WPF app
I'm creating a full-screen application in WPF and i need to choose how to actually resize the contents to use all the available space on the screen.

As far as i know, there are 2 solutions:

Grids with stars-dimensions

ViewBox wrapper

I think they both do the job but depending on the application one is better than the other: when should the grid approach be used? And when the viewbox method is acceptable?

答: A Grid is always going to give you more flexibility than a ViewBox, what if you want some components of your application to have fixed heights / widths? For example the panels at the side of visual studio do not change in size as the application window size changes.</p>

ContentLicense: CC BY-SA 3.0


问:
Return Data of two tables using mysql join as one java Object in Spring boot
CPT Table

```<code>@Entity
@Table(name = "CPT")
public class CPTCodeset {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "Id")
    private int id;

    @Column(name = "Code")
    private String code;

    @Column(name = "Description")
    private String desc;
//getters and setters
}
</code>```

CPT Procedures Table

```<code>@Entity
@Table(name = "cptprocedures")
public class CPTProcedures {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "Id")
    private int Id;

    @OneToOne(fetch=FetchType.EAGER)
    @JoinColumn(name = "ProcedureId")
    private Procedure procedure;
    @Transient
    private int procedureId;

    @OneToOne(fetch=FetchType.EAGER)
    @JoinColumn(name = "CPTCodeSet")
    private CPTCodeset cpt;
    @Transient
    private int cptCodeSet;
//getters and setters
}
</code>```

CPTRepository

```<code>@Query(nativeQuery = true, value = "SELECT cp.ProcedureId,c.Code,c.Description FROM cptprocedures cp JOIN CPT c ON cp.CPTCodeSet = c.Id where c.Description like \"%ane\";")
List<CPTCodeset> findBySearch(@Param("searchString") String searchString);
</code>```

This Query Returning Data is what I want. But how can I map this data into a single object where as it includes 2 tables.

How can I do it by using @Entity without creating a table. Any suggestions?

答:
You should replace desc field name. It’s better not to use JPA reserved words

```<code>@Entity
@Table(name = "CPT")
public class CPTCodeset {
    //fields

    @Column(name = "Description")
    private String description;

    //getters and setters
}
</code>```

To get query result as List<Object[]>

```<code>@Query("select cp.procedure.id, c.code, c.description "
         + "from CPTProcedures cp join cp.cpt c "
         + "where c.description like :searchString")
List<Object[]> findBySearch(@Param("searchString") String searchString);
</code>```

or create DTO class with appropriate constructor SearchResultDto(int, String, String) and use this

```<code>@Query("select new yourproject.dto.SearchResultDto(cp.procedure.id, c.code, c.description) "
         + "from CPTProcedures cp join cp.cpt c "
         + "where c.description like :searchString")
List<SearchResultDto> findBySearch(@Param("searchString") String searchString);
</code>```

Repository usage:

```<code>// description contains searchString
List<SearchResultDto> dtos1 = repository.findBySearch("%" + searchString + "%");

// description start with searchString
List<SearchResultDto> dtos2 = repository.findBySearch("%" + searchString);

// description end with searchString
List<SearchResultDto> dtos3 = repository.findBySearch(searchString + "%");
</code>```

Body:
CPT Table

@Entity
@Table(name = "CPT")
public class CPTCodeset {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "Id")
    private int id;

    @Column(name = "Code")
    private String code;

    @Column(name = "Description")
    private String desc;
//getters and setters
}

CPT Procedures Table

@Entity
@Table(name = "cptprocedures")
public class CPTProcedures {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "Id")
    private int Id;

    @OneToOne(fetch=FetchType.EAGER)
    @JoinColumn(name = "ProcedureId")
    private Procedure procedure;
    @Transient
    private int procedureId;

    @OneToOne(fetch=FetchType.EAGER)
    @JoinColumn(name = "CPTCodeSet")
    private CPTCodeset cpt;
    @Transient
    private int cptCodeSet;
//getters and setters
}

CPTRepository

@Query(nativeQuery = true, value = "SELECT cp.ProcedureId,c.Code,c.Description FROM cptprocedures cp JOIN CPT c ON cp.CPTCodeSet = c.Id where c.Description like \"%ane\";")
List<CPTCodeset> findBySearch(@Param("searchString") String searchString);

This Query Returning Data is what I want. But how can I map this data into a single object where as it includes 2 tables.

How can I do it by using @Entity without creating a table. Any suggestions?

Body:
You should replace desc field name. It’s better not to use JPA reserved words

@Entity
@Table(name = "CPT")
public class CPTCodeset {
    //fields

    @Column(name = "Description")
    private String description;

    //getters and setters
}

To get query result as List<Object[]>

@Query("select cp.procedure.id, c.code, c.description "
         + "from CPTProcedures cp join cp.cpt c "
         + "where c.description like :searchString")
List<Object[]> findBySearch(@Param("searchString") String searchString);

or create DTO class with appropriate constructor SearchResultDto(int, String, String) and use this

@Query("select new yourproject.dto.SearchResultDto(cp.procedure.id, c.code, c.description) "
         + "from CPTProcedures cp join cp.cpt c "
         + "where c.description like :searchString")
List<SearchResultDto> findBySearch(@Param("searchString") String searchString);

Repository usage:

// description contains searchString
List<SearchResultDto> dtos1 = repository.findBySearch("%" + searchString + "%");

// description start with searchString
List<SearchResultDto> dtos2 = repository.findBySearch("%" + searchString);

// description end with searchString
List<SearchResultDto> dtos3 = repository.findBySearch(searchString + "%");


问:
DynamoDB find all items after date
I have a DynamoDB table in which I store link data (url, date, category, tags etc).

I need to be able to -

lookup items by url (check url doesn't already exist)

find all items stored after a given date

Based on the above I set up the schema with url as primary hash key and secondary index on date, as follows -

```<code>AWSTemplateFormatVersion: '2010-09-09'
Parameters:
  TableName:
    Type: String
    Default: "my_links"
  HashAttr:
    Type: String
    Default: url
  IndexAttr:
    Type: String
    Default: date
  ReadCapacity:
    Type: Number
    Default: 5
  WriteCapacity:
    Type: Number
    Default: 5
Resources:
  Table:
    Properties:
      KeySchema:
        - AttributeName: !Ref HashAttr
          KeyType: HASH
      AttributeDefinitions:
        - AttributeName: !Ref HashAttr
          AttributeType: S
        - AttributeName: !Ref IndexAttr
          AttributeType: S
      GlobalSecondaryIndexes:
        - IndexName: !Ref IndexAttr
          KeySchema:
            - AttributeName: !Ref IndexAttr
              KeyType: HASH
          Projection:
            ProjectionType: ALL
          ProvisionedThroughput:
            ReadCapacityUnits: !Ref ReadCapacity
            WriteCapacityUnits: !Ref WriteCapacity
      ProvisionedThroughput:
        ReadCapacityUnits: !Ref ReadCapacity
        WriteCapacityUnits: !Ref WriteCapacity
      TableName: !Ref TableName
    Type: AWS::DynamoDB::Table
</code>```

I can query the table by date as follows, but only using an eq condition -

```<code>ddb=boto3.resource("dynamodb")
table=ddb.Table("my_links")
from boto3.dynamodb.conditions import Key
queryexp=Key('date').eq("2020-02-19")
for item in table.query(IndexName="date",
                        KeyConditionExpression=queryexp)["Items"]:
    print (item)
</code>```

If I use a gte in place of eq condition I get the following -

```<code>botocore.exceptions.ClientError: An error occurred (ValidationException) when calling the Query operation: Query key condition not supported
</code>```

I can however query the table using a scan and a gte condition -

```<code>filterexp=Key('date').gte("2020-02-19")
for item in table.scan(FilterExpression=filterexp)["Items"]:
    print (item)
</code>```

But then I'm guessing I don't need the secondary index any more and also that this will get very expensive as the table get large :-/

So I'd rather stick with a secondary index and query if possible (am I thinking about this right ?), but what do I need to do to the schema to be able to fetch all items after a date ?

答:
You can't use GTE.
Queries support EQ | LE | LT | GE | GT | BEGINS_WITH | BETWEEN

Check this article https://medium.com/cloud-native-the-gathering/querying-dynamodb-by-date-range-899b751a6ef2

Title: DynamoDB find all items after date

Body:
I have a DynamoDB table in which I store link data (url, date, category, tags etc).

I need to be able to -

lookup items by url (check url doesn't already exist)

find all items stored after a given date

Based on the above I set up the schema with url as primary hash key and secondary index on date, as follows -

AWSTemplateFormatVersion: '2010-09-09'
Parameters:
  TableName:
    Type: String
    Default: "my_links"
  HashAttr:
    Type: String
    Default: url
  IndexAttr:
    Type: String
    Default: date
  ReadCapacity:
    Type: Number
    Default: 5
  WriteCapacity:
    Type: Number
    Default: 5
Resources:
  Table:
    Properties:
      KeySchema:
        - AttributeName: !Ref HashAttr
          KeyType: HASH
      AttributeDefinitions:
        - AttributeName: !Ref HashAttr
          AttributeType: S
        - AttributeName: !Ref IndexAttr
          AttributeType: S
      GlobalSecondaryIndexes:
        - IndexName: !Ref IndexAttr
          KeySchema:
            - AttributeName: !Ref IndexAttr
              KeyType: HASH
          Projection:
            ProjectionType: ALL
          ProvisionedThroughput:
            ReadCapacityUnits: !Ref ReadCapacity
            WriteCapacityUnits: !Ref WriteCapacity
      ProvisionedThroughput:
        ReadCapacityUnits: !Ref ReadCapacity
        WriteCapacityUnits: !Ref WriteCapacity
      TableName: !Ref TableName
    Type: AWS::DynamoDB::Table

I can query the table by date as follows, but only using an eq condition -

ddb=boto3.resource("dynamodb")
table=ddb.Table("my_links")
from boto3.dynamodb.conditions import Key
queryexp=Key('date').eq("2020-02-19")
for item in table.query(IndexName="date",
                        KeyConditionExpression=queryexp)["Items"]:
    print (item)

If I use a gte in place of eq condition I get the following -

botocore.exceptions.ClientError: An error occurred (ValidationException) when calling the Query operation: Query key condition not supported

I can however query the table using a scan and a gte condition -

filterexp=Key('date').gte("2020-02-19")
for item in table.scan(FilterExpression=filterexp)["Items"]:
    print (item)

But then I'm guessing I don't need the secondary index any more and also that this will get very expensive as the table get large :-/

So I'd rather stick with a secondary index and query if possible (am I thinking about this right ?), but what do I need to do to the schema to be able to fetch all items after a date ?


问:
Array of objects how do i check for deeply nested text string duplicates & remove from array?
I have an array of objects
Deep inside those objects is a text string
I want to check if other objects in the same array have the same text string / are duplicates.
Then i need a new array with those duplicates removed.

I thought this would be quite simple but it's been testing my intellect for two days now.

```<code>const arr = [
   {..obj 1}
   {..obj 2}
   {..obj 3}
   {
      id: 4,
      uid: 24872-2847-249249892842,
      tags: ['some', 'stuff'],
      type: "blogpage",
      href: "https://link-to-stuff",
      first_publication_date: "2020-02-12T16:05:04+0000",
      last_publication_date: "2020-02-18T21:52:06+0000",
      data: {
            ...some stuff
                  heading: [
                        { type: "heading1", text: "Here Is My Text I Need To Check Duplicates
                   Of"}
                  ]
      }

   }
   {..obj 5}
   {..obj 6}
   {..obj 7}
   {..obj 8}
   {..obj 9}
   {..obj 10}
]

I figured something like:

</code>```

filterOutDuplicates = (blogIndexContent) => {

```<code>let arr = blogIndexContent.pages;

let results = [];

arr.map(each => {
  if (!results || !results.length) {
    results.push(each);
  } else {
    for (let i = 0; i < results.length; i++) {
      const headline = results[i].data.heading[0].text;
      if (headline === each.data.heading[0].text) {
        return;
      } else {
        return results.push(each);
      }
    }
  }
})

console.log('Results :', results); // <-- this just gives me the same 9 blog stories again, no duplicates removed.
</code>```

}

```<code>
What am i doing wrong guys?
</code>```

答:
This should work for you:</p>

```<code>filterOutDuplicates = blogIndexContent => {
  let arr = blogIndexContent.pages

  const result = []
  arr.forEach(each => {
    if (result.length === 0) {
      result.push(each)
    }
    else {
      const headline = each.data.heading[0].text
      let found = false
      for (let i = 0; i < result.length; i++) {
        if (result[i].data.heading[0].text === headline) {
          found = true
          break
        }
      }
      if (!found) {
        result.push(each)
      }
    }
  })

  console.log('Results :', results)
}
</code>```

Body:
I have an array of objects
Deep inside those objects is a text string
I want to check if other objects in the same array have the same text string / are duplicates.
Then i need a new array with those duplicates removed.

I thought this would be quite simple but it's been testing my intellect for two days now.

const arr = [
   {..obj 1}
   {..obj 2}
   {..obj 3}
   {
      id: 4,
      uid: 24872-2847-249249892842,
      tags: ['some', 'stuff'],
      type: "blogpage",
      href: "https://link-to-stuff",
      first_publication_date: "2020-02-12T16:05:04+0000",
      last_publication_date: "2020-02-18T21:52:06+0000",
      data: {
            ...some stuff
                  heading: [
                        { type: "heading1", text: "Here Is My Text I Need To Check Duplicates
                   Of"}
                  ]
      }

   }
   {..obj 5}
   {..obj 6}
   {..obj 7}
   {..obj 8}
   {..obj 9}
   {..obj 10}
]

I figured something like:

filterOutDuplicates = (blogIndexContent) => {

let arr = blogIndexContent.pages;

let results = [];

arr.map(each => {
  if (!results || !results.length) {
    results.push(each);
  } else {
    for (let i = 0; i < results.length; i++) {
      const headline = results[i].data.heading[0].text;
      if (headline === each.data.heading[0].text) {
        return;
      } else {
        return results.push(each);
      }
    }
  }
})

console.log('Results :', results); // <-- this just gives me the same 9 blog stories again, no duplicates removed.

}

What am i doing wrong guys?

Body:
This should work for you:

filterOutDuplicates = blogIndexContent => {
  let arr = blogIndexContent.pages

  const result = []
  arr.forEach(each => {
    if (result.length === 0) {
      result.push(each)
    }
    else {
      const headline = each.data.heading[0].text
      let found = false
      for (let i = 0; i < result.length; i++) {
        if (result[i].data.heading[0].text === headline) {
          found = true
          break
        }
      }
      if (!found) {
        result.push(each)
      }
    }
  })

  console.log('Results :', results)
}


问:
What does a lock statement do under the hood?
I see that for using objects which are not thread safe we wrap the code with a lock like this:

```<code>private static readonly Object obj = new Object();

lock (obj)
{
    // thread unsafe code
}
</code>```

So, what happens when multiple threads access the same code (let's assume that it is running in a ASP.NET web application). Are they queued? If so how long will they wait?

What is the performance impact because of using locks?

答:
The performance impact depends on the way you lock. You can find a good list of optimizations here: http://www.thinkingparallel.com/2007/07/31/10-ways-to-reduce-lock-contention-in-threaded-programs/

Basically you should try to lock as little as possible, since it puts your waiting code to sleep. If you have some heavy calculations or long lasting code (e.g. file upload) in a lock it results in a huge performance loss.

Body:
I see that for using objects which are not thread safe we wrap the code with a lock like this:

private static readonly Object obj = new Object();

lock (obj)
{
    // thread unsafe code
}

So, what happens when multiple threads access the same code (let's assume that it is running in a ASP.NET web application). Are they queued? If so how long will they wait?

What is the performance impact because of using locks?


问:
How to compare date if one column has start and end date
The column has a start and end date

```<code>month_name
23 March, 2018 - 23 April, 2018
</code>```

23 March, 2018 is the start date and 23 April, 2018 is the end date

How can I use them as to the start date and end date to query?

答:
You would need to use SUBSTRING_INDEX to return a part of the string to the left or right of the hyphen. But this would be terrible in terms of performance. So you need to look at your data structure and redesign accordingly. The start and end dates should be in distinct columns with an INDEX and appropriate DATATYPE set (DATETIME, TIMESTAMP, DATE).

I would suggest that you process the text prior to saving to the database, by using client language regex or split/substring functionality to correctly format the dates into MYSQL format before saving.

Body:
The column has a start and end date

month_name
23 March, 2018 - 23 April, 2018

23 March, 2018 is the start date and 23 April, 2018 is the end date

How can I use them as to the start date and end date to query?


问:
Jenkins and Github trigger PUSH from specific branch
I set up the Github webhook in Jenkins and I created a job with the following configuration:

However, every time I push something from any branch, the job build a new version (using the branch which I specified).

I set up the job by reading some related questions on Stackoverflow but all those questions are quite old and without a clear solution:

GitHub WebHooks triggered globally instead of per branch

Trigger Jenkins job on GitHub PUSH to specific branch

Is it possible to trigger Push only from a specific branch?

答:
You are using a GitHub Webhook to trigger a preconfigured job. Your Job has the Branch "JENKINS-TEST-AUTODEPLOYMENT" hardcoded, so it will always build this branch only, no matter which branch you are pushing on GitHub.

How about using GitHub Branch Source Plugin?
With this Plugin, Hooks will be auto-created in github for the corresponding repos. Each Branch will have a job in jenkins, which is also auto-created as long as you have a Jenkinsfile inside your Repo. With this your desired state should be easily achievable.


问:
How can I create this kinda of URL /{storeId}/employee with Laravel
I'm using Laravel 6.x to create a simple store management dashboard, and this is how I think it should work:

The owner login in our system

Select one store of a list that he owns

Now he would be redirect to a dashboard to that specific store
I was thinking in do something like this: http://127.0.0.1:8000/{storeId}/home and with the storeId the dashboard could show every information related to it, I know how to do it in a totally improper way, something like:

Route::group(
    [
        'middleware' => 'auth'
    ], function(){
        Route::resource('/stores', 'StoreController');
        Route::resource('/{storeId}/warehouse', 'WarehouseController');
        Route::resource('/{storeId}/employees', 'EmployeesController');
    }
);
```

I kinda don't wan't to repeat the /{storeId} in every route, exist something to avoid it?
I thought to use the Sub-domain Routing, but I think it doesn't fit in this case.

答:
You can use Route Groups

```<code>Route::group(['prefix' => '{storeId}'], function () {
    Route::resource('/warehouse', 'WarehouseController');
    Route::resource('/employees', 'EmployeesController');
})
</code>```

You can also go though Get Dynamic Route Group Prefix Parameter example.

Body:
I'm using Laravel 6.x to create a simple store management dashboard, and this is how I think it should work:

The owner login in our system

Select one store of a list that he owns

Now he would be redirect to a dashboard to that specific store
I was thinking in do something like this: http://127.0.0.1:8000/{storeId}/home and with the storeId the dashboard could show every information related to it, I know how to do it in a totally improper way, something like:

Route::group(
    [
        'middleware' => 'auth'
    ], function(){
        Route::resource('/stores', 'StoreController');
        Route::resource('/{storeId}/warehouse', 'WarehouseController');
        Route::resource('/{storeId}/employees', 'EmployeesController');
    }
);

I kinda don't wan't to repeat the /{storeId} in every route, exist something to avoid it?
I thought to use the Sub-domain Routing, but I think it doesn't fit in this case.

Body:
You can use Route Groups

Route::group(['prefix' => '{storeId}'], function () {
    Route::resource('/warehouse', 'WarehouseController');
    Route::resource('/employees', 'EmployeesController');
})

You can also go though Get Dynamic Route Group Prefix Parameter example.


问:
How do I look for a byte sequence in a file?
I want to finde this arrange of bytes in a file :

[18][53][80][67] (HEX)
00011000 1010011 10000000 1100111

The bytes represent Matroska Segment EBML ID  https://www.matroska.org/technical/specs/index.html

I try to search in the file like this but with no results :

```<code>    is.seekg (0, is.end);
    int length = is.tellg();
    is.seekg (0, is.beg);

    char * buffer = new char [8];

    std::cout << "Reading " << length << " characters... ";
    // read data as a block:
      for(int i=0;i<length;i++){
       std::cout<<i<<std::endl;
       is.read (buffer,sizeof(char));
       if((int)(unsigned  char)buffer[0] == 1)
           if((int)(unsigned  char)buffer[1] == 8)
               if((int)(unsigned  char)buffer[3] == 10)
                   if((int)(unsigned  char)buffer[4] == 3)
                       if((int)(unsigned  char)buffer[5]==8)
                           if((int)(unsigned  char)buffer[6]==0)
                               if((int)(unsigned  char)buffer[7]==12)
                                   if((int)(unsigned  char)buffer[8]==7)
                                       std::cout<<"finish !!!!";
</code>```

Is my approach wrong?

答:
First of all you have to remember that each hexadecimal number you show (e.g. 18) is a single byte. That is you need to read and check four bytes instead of eight.

Secondly, you don't have to compare all bytes individually, you can read four bytes at a time and compare against an array of bytes containing the data you need to find:

```<code>// The data we need to find in the file
uint8_t data_to_find[] = { 0x18, 0x53, 0x80, 0x67 };

// The data from the file
uint8_t current_data[sizeof data_to_find];
</code>```

Then read sizeof current_data bytes into the current_data array, and compare against data_to_find:

```<code>if (std::memcmp(data_to_find, current_data, sizeof data_to_find) == 0)
{
    // Found the data
}
else
{
    // Didn't find the data
}
</code>```

Body:
I want to finde this arrange of bytes in a file :

[18][53][80][67] (HEX)
00011000 1010011 10000000 1100111

The bytes represent Matroska Segment EBML ID  https://www.matroska.org/technical/specs/index.html

I try to search in the file like this but with no results :

    is.seekg (0, is.end);
    int length = is.tellg();
    is.seekg (0, is.beg);

    char * buffer = new char [8];

    std::cout << "Reading " << length << " characters... ";
    // read data as a block:
      for(int i=0;i<length;i++){
       std::cout<<i<<std::endl;
       is.read (buffer,sizeof(char));
       if((int)(unsigned  char)buffer[0] == 1)
           if((int)(unsigned  char)buffer[1] == 8)
               if((int)(unsigned  char)buffer[3] == 10)
                   if((int)(unsigned  char)buffer[4] == 3)
                       if((int)(unsigned  char)buffer[5]==8)
                           if((int)(unsigned  char)buffer[6]==0)
                               if((int)(unsigned  char)buffer[7]==12)
                                   if((int)(unsigned  char)buffer[8]==7)
                                       std::cout<<"finish !!!!";

Is my approach wrong?

Body:
First of all you have to remember that each hexadecimal number you show (e.g. 18) is a single byte. That is you need to read and check four bytes instead of eight.

Secondly, you don't have to compare all bytes individually, you can read four bytes at a time and compare against an array of bytes containing the data you need to find:

// The data we need to find in the file
uint8_t data_to_find[] = { 0x18, 0x53, 0x80, 0x67 };

// The data from the file
uint8_t current_data[sizeof data_to_find];

Then read sizeof current_data bytes into the current_data array, and compare against data_to_find:

if (std::memcmp(data_to_find, current_data, sizeof data_to_find) == 0)
{
    // Found the data
}
else
{
    // Didn't find the data
}


问:
Firebase not sending verification code to phone the second time
In my app, I'm using Firebase to verify the user's phone number. However, the verification system is inconsistent and sends the OTP only the first time. For example, I get the OTP when I'm signing in for the first time, but if I sign out and try to sign in again, I don't get the OTP.

This is the activity where the user is asked to enter the OTP:

```<code>import android.app.ProgressDialog;
import android.content.Intent;
import android.os.Bundle;
import android.os.CountDownTimer;
import android.view.View;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;

import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;

import com.google.android.gms.tasks.OnCompleteListener;
import com.google.android.gms.tasks.Task;
import com.google.android.material.floatingactionbutton.FloatingActionButton;
import com.google.android.material.snackbar.Snackbar;
import com.google.firebase.FirebaseException;
import com.google.firebase.auth.AuthResult;
import com.google.firebase.auth.FirebaseAuth;
import com.google.firebase.auth.PhoneAuthCredential;
import com.google.firebase.auth.PhoneAuthProvider;
import com.google.firebase.firestore.FirebaseFirestore;
import com.google.firebase.firestore.QueryDocumentSnapshot;
import com.google.firebase.firestore.QuerySnapshot;
import com.google.firebase.iid.FirebaseInstanceId;
import com.google.firebase.iid.InstanceIdResult;

import java.util.concurrent.TimeUnit;

public class EnterOTPActivity extends AppCompatActivity {
    String userPhoneNumber;

    private int autoResendCount=0, resumeCount=0;
    private final String ctryCode = "+91";
    private String verificationId;
    private FirebaseAuth mAuth;
    private TextView resendOtp, enterOtpMessage, timerTV;
    private ProgressDialog progressDialog;
    private EditText otpField;
    private boolean firstSend=true,timerOn=true;
    FirebaseFirestore db;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_enter_otp);
        mAuth = FirebaseAuth.getInstance();
        otpField = findViewById(R.id.editTextOtp);
        resendOtp =  findViewById(R.id.resendOTPButton);
        timerTV = findViewById(R.id.resendTimer);
        userPhoneNumber = getIntent().getStringExtra("USER_MOB").trim();
        sendVerificationCode(userPhoneNumber);
        startResendTimer(15);
        getSupportActionBar().setTitle("Verification");
        resendOtp.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                if (!timerOn) {
                    startResendTimer(30);
                    firstSend = false;
                    sendVerificationCode(userPhoneNumber);
                }
            }
        });
        FloatingActionButton next = findViewById(R.id.fab2);
        enterOtpMessage =  findViewById(R.id.aboutotpverif);
        enterOtpMessage.setText(enterOtpMessage.getText().toString() + " " + ctryCode + userPhoneNumber);
        progressDialog = new ProgressDialog(this);
        progressDialog.setMessage("Please wait while we check your verification code");
        progressDialog.setTitle("Verification");
        progressDialog.setCancelable(false);
        next.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                //check if otp is correct here
                if (otpField.getText().toString().length() == 6) {
                    verifyCode(otpField.getText().toString().trim());
                    if(!progressDialog.isShowing())
                    progressDialog.show();
                } else {
                    View parentLayout = findViewById(android.R.id.content);
                    Snackbar.make(parentLayout, "A valid verification code has 6 digits", Snackbar.LENGTH_SHORT)
                            .setAction("OKAY", new View.OnClickListener() {
                                @Override
                                public void onClick(View view) {

                                }
                            })
                            .setActionTextColor(getResources().getColor(android.R.color.holo_red_light))
                            .show();
                }
            }
        });
    }

    private void verifyCode(String code) {

        try {
            PhoneAuthCredential credential = PhoneAuthProvider.getCredential(verificationId, code);
            signInwithCredential(credential);

        }
        catch (Exception e) {
            // code here is executed when we don't get the OTP and enter a wrong one
            progressDialog.dismiss();
            progressDialog.setCancelable(true);
            View parentLayout = findViewById(android.R.id.content);
            Snackbar.make(parentLayout, getString(R.string.incorrect_code_t1), Snackbar.LENGTH_LONG)
                    .setAction("OKAY", new View.OnClickListener() {
                        @Override
                        public void onClick(View view) {

                        }
                    })
                    .setActionTextColor(getResources().getColor(android.R.color.holo_red_light))
                    .show();
            if(progressDialog.isShowing())
            progressDialog.dismiss();
        }
    }

    private void signInwithCredential(PhoneAuthCredential credential) {
        mAuth.signInWithCredential(credential).addOnCompleteListener(new OnCompleteListener<AuthResult>() {
            @Override
            public void onComplete(@NonNull Task<AuthResult> task) {
                if (task.isSuccessful()) {
                    isRegisteredUser();
                }
                else {
                    if(progressDialog.isShowing())
                    progressDialog.dismiss();
                    View parentLayout = findViewById(android.R.id.content);
                    Snackbar.make(parentLayout, "Incorrect verification code", Snackbar.LENGTH_SHORT)
                            .setAction("OKAY", new View.OnClickListener() {
                                @Override
                                public void onClick(View view) {

                                }
                            })
                            .setActionTextColor(getResources().getColor(android.R.color.holo_red_light))
                            .show();
                    if(progressDialog.isShowing())
                    progressDialog.dismiss();

                }
            }
        });

    }

    private void sendVerificationCode(String number) {
        final String phoneNumber = ctryCode + number;
        PhoneAuthProvider.getInstance().verifyPhoneNumber(
                phoneNumber,        // Phone number to verify
                120,                 // Timeout duration
                TimeUnit.SECONDS,   // Unit of timeout
                this,               // Activity (for callback binding)
                mCallbacks);        // OnVerificationStateChangedCallbacks
    }

    private PhoneAuthProvider.OnVerificationStateChangedCallbacks mCallbacks = new PhoneAuthProvider.OnVerificationStateChangedCallbacks() {

        @Override
        public void onCodeSent(@NonNull String s, @NonNull PhoneAuthProvider.ForceResendingToken forceResendingToken) {
            super.onCodeSent(s, forceResendingToken);
            verificationId = s;
        }

        @Override
        public void onVerificationCompleted(@NonNull PhoneAuthCredential phoneAuthCredential) {
            String code = phoneAuthCredential.getSmsCode();
            if (code != null) {
                verifyCode(code);
                otpField.setText(code);
                if(!progressDialog.isShowing())
                progressDialog.show();
            }
        }

        @Override
        public void onVerificationFailed(@NonNull FirebaseException e) {
            Toast.makeText(getApplicationContext(), e.getMessage(), Toast.LENGTH_LONG).show();
        }
    };

    private void isRegisteredUser() {

        final String userId = ctryCode + userPhoneNumber;
        db = FirebaseFirestore.getInstance();
        db.collection("users")
                .whereEqualTo("phone", userId)
                .get()
                .addOnCompleteListener(new OnCompleteListener<QuerySnapshot>() {

                    @Override
                    public void onComplete(@NonNull Task<QuerySnapshot> task) {
                        try{
                        if (task.isSuccessful()) {

                            saveToken(userId);

                            for (QueryDocumentSnapshot document : task.getResult()) {
                                if (document.getId().equalsIgnoreCase(userId)) {

                                    Intent startmainact = new Intent(EnterOTPActivity.this, MainActivity.class);
                                    startmainact.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
                                    startActivity(startmainact);
                                    finish();
                                    return;
                                }
                                //Log.d(TAG, document.getId() + " => " + document.getData());
                            }

                            Intent startposact = new Intent(EnterOTPActivity.this, ParOrStudActivity.class);

                            startposact.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
                            startActivity(startposact);
                            finish();

                        } else {
                            View parentLayout = findViewById(android.R.id.content);
                            Snackbar.make(parentLayout, "Database error: please try again", Snackbar.LENGTH_SHORT)
                                    .setAction("OKAY", new View.OnClickListener() {
                                        @Override
                                        public void onClick(View view) {

                                        }
                                    })
                                    .setActionTextColor(getResources().getColor(android.R.color.holo_red_light))
                                    .show();
                        }
                    }
                        catch(Exception e){
                            View parentLayout = findViewById(android.R.id.content);
                            Snackbar.make(parentLayout, "Database error: please try again", Snackbar.LENGTH_SHORT)
                                    .setAction("OKAY", new View.OnClickListener() {
                                        @Override
                                        public void onClick(View view) {

                                        }
                                    })
                                    .setActionTextColor(getResources().getColor(android.R.color.holo_red_light))
                                    .show();
                        }
                    }

                });
    }

    private void saveToken(final String userId) {
        FirebaseInstanceId.getInstance().getInstanceId()
                .addOnCompleteListener(new OnCompleteListener<InstanceIdResult>() {
                    @Override
                    public void onComplete(@NonNull Task<InstanceIdResult> task) {
                        if (!task.isSuccessful()) {
                            return;
                        }

                        // Get new Instance ID token
                        String token = task.getResult().getToken();
                        FirebaseFirestore.getInstance().collection("users").document(userId).update("token",token);
                    }
                });
    }

    @Override
    protected void onResume() {
        super.onResume();
        if (autoResendCount<2 && resumeCount>0) {
            sendVerificationCode(userPhoneNumber);
            autoResendCount=autoResendCount+1;
            resumeCount=resumeCount+1;
        }
    }

    @Override
    protected void onStop() {
        super.onStop();
        progressDialog.dismiss();
    }

    public void startResendTimer(int seconds) {
        timerTV.setVisibility(View.VISIBLE);
        resendOtp.setEnabled(false);

        new CountDownTimer(seconds*1000, 1000) {

            public void onTick(long millisUntilFinished) {
                String secondsString = Long.toString(millisUntilFinished/1000);
                if (millisUntilFinished<10000) {
                    secondsString = "0"+secondsString;
                }
                timerTV.setText(" (0:"+ secondsString+")");
            }

            public void onFinish() {
                resendOtp.setEnabled(true);
                timerTV.setVisibility(View.GONE);
                timerOn=false;
            }
        }.start();
    }

    @Override
    public void onBackPressed() {
        // do not allow user to go back to the screen before
    }
}
</code>```

This erratic verification system delivers an incompetent UX. Is there any way to get around it?

答: You just try to Logout from your app or one more thing you can do is to clear app data or you can reinstall.</p>

Body:
In my app, I'm using Firebase to verify the user's phone number. However, the verification system is inconsistent and sends the OTP only the first time. For example, I get the OTP when I'm signing in for the first time, but if I sign out and try to sign in again, I don't get the OTP.

This is the activity where the user is asked to enter the OTP:

import android.app.ProgressDialog;
import android.content.Intent;
import android.os.Bundle;
import android.os.CountDownTimer;
import android.view.View;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;

import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;

import com.google.android.gms.tasks.OnCompleteListener;
import com.google.android.gms.tasks.Task;
import com.google.android.material.floatingactionbutton.FloatingActionButton;
import com.google.android.material.snackbar.Snackbar;
import com.google.firebase.FirebaseException;
import com.google.firebase.auth.AuthResult;
import com.google.firebase.auth.FirebaseAuth;
import com.google.firebase.auth.PhoneAuthCredential;
import com.google.firebase.auth.PhoneAuthProvider;
import com.google.firebase.firestore.FirebaseFirestore;
import com.google.firebase.firestore.QueryDocumentSnapshot;
import com.google.firebase.firestore.QuerySnapshot;
import com.google.firebase.iid.FirebaseInstanceId;
import com.google.firebase.iid.InstanceIdResult;

import java.util.concurrent.TimeUnit;

public class EnterOTPActivity extends AppCompatActivity {
    String userPhoneNumber;

    private int autoResendCount=0, resumeCount=0;
    private final String ctryCode = "+91";
    private String verificationId;
    private FirebaseAuth mAuth;
    private TextView resendOtp, enterOtpMessage, timerTV;
    private ProgressDialog progressDialog;
    private EditText otpField;
    private boolean firstSend=true,timerOn=true;
    FirebaseFirestore db;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_enter_otp);
        mAuth = FirebaseAuth.getInstance();
        otpField = findViewById(R.id.editTextOtp);
        resendOtp =  findViewById(R.id.resendOTPButton);
        timerTV = findViewById(R.id.resendTimer);
        userPhoneNumber = getIntent().getStringExtra("USER_MOB").trim();
        sendVerificationCode(userPhoneNumber);
        startResendTimer(15);
        getSupportActionBar().setTitle("Verification");
        resendOtp.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                if (!timerOn) {
                    startResendTimer(30);
                    firstSend = false;
                    sendVerificationCode(userPhoneNumber);
                }
            }
        });
        FloatingActionButton next = findViewById(R.id.fab2);
        enterOtpMessage =  findViewById(R.id.aboutotpverif);
        enterOtpMessage.setText(enterOtpMessage.getText().toString() + " " + ctryCode + userPhoneNumber);
        progressDialog = new ProgressDialog(this);
        progressDialog.setMessage("Please wait while we check your verification code");
        progressDialog.setTitle("Verification");
        progressDialog.setCancelable(false);
        next.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                //check if otp is correct here
                if (otpField.getText().toString().length() == 6) {
                    verifyCode(otpField.getText().toString().trim());
                    if(!progressDialog.isShowing())
                    progressDialog.show();
                } else {
                    View parentLayout = findViewById(android.R.id.content);
                    Snackbar.make(parentLayout, "A valid verification code has 6 digits", Snackbar.LENGTH_SHORT)
                            .setAction("OKAY", new View.OnClickListener() {
                                @Override
                                public void onClick(View view) {

                                }
                            })
                            .setActionTextColor(getResources().getColor(android.R.color.holo_red_light))
                            .show();
                }
            }
        });
    }

    private void verifyCode(String code) {

        try {
            PhoneAuthCredential credential = PhoneAuthProvider.getCredential(verificationId, code);
            signInwithCredential(credential);

        }
        catch (Exception e) {
            // code here is executed when we don't get the OTP and enter a wrong one
            progressDialog.dismiss();
            progressDialog.setCancelable(true);
            View parentLayout = findViewById(android.R.id.content);
            Snackbar.make(parentLayout, getString(R.string.incorrect_code_t1), Snackbar.LENGTH_LONG)
                    .setAction("OKAY", new View.OnClickListener() {
                        @Override
                        public void onClick(View view) {

                        }
                    })
                    .setActionTextColor(getResources().getColor(android.R.color.holo_red_light))
                    .show();
            if(progressDialog.isShowing())
            progressDialog.dismiss();
        }
    }

    private void signInwithCredential(PhoneAuthCredential credential) {
        mAuth.signInWithCredential(credential).addOnCompleteListener(new OnCompleteListener<AuthResult>() {
            @Override
            public void onComplete(@NonNull Task<AuthResult> task) {
                if (task.isSuccessful()) {
                    isRegisteredUser();
                }
                else {
                    if(progressDialog.isShowing())
                    progressDialog.dismiss();
                    View parentLayout = findViewById(android.R.id.content);
                    Snackbar.make(parentLayout, "Incorrect verification code", Snackbar.LENGTH_SHORT)
                            .setAction("OKAY", new View.OnClickListener() {
                                @Override
                                public void onClick(View view) {

                                }
                            })
                            .setActionTextColor(getResources().getColor(android.R.color.holo_red_light))
                            .show();
                    if(progressDialog.isShowing())
                    progressDialog.dismiss();

                }
            }
        });

    }

    private void sendVerificationCode(String number) {
        final String phoneNumber = ctryCode + number;
        PhoneAuthProvider.getInstance().verifyPhoneNumber(
                phoneNumber,        // Phone number to verify
                120,                 // Timeout duration
                TimeUnit.SECONDS,   // Unit of timeout
                this,               // Activity (for callback binding)
                mCallbacks);        // OnVerificationStateChangedCallbacks
    }

    private PhoneAuthProvider.OnVerificationStateChangedCallbacks mCallbacks = new PhoneAuthProvider.OnVerificationStateChangedCallbacks() {

        @Override
        public void onCodeSent(@NonNull String s, @NonNull PhoneAuthProvider.ForceResendingToken forceResendingToken) {
            super.onCodeSent(s, forceResendingToken);
            verificationId = s;
        }

        @Override
        public void onVerificationCompleted(@NonNull PhoneAuthCredential phoneAuthCredential) {
            String code = phoneAuthCredential.getSmsCode();
            if (code != null) {
                verifyCode(code);
                otpField.setText(code);
                if(!progressDialog.isShowing())
                progressDialog.show();
            }
        }

        @Override
        public void onVerificationFailed(@NonNull FirebaseException e) {
            Toast.makeText(getApplicationContext(), e.getMessage(), Toast.LENGTH_LONG).show();
        }
    };

    private void isRegisteredUser() {

        final String userId = ctryCode + userPhoneNumber;
        db = FirebaseFirestore.getInstance();
        db.collection("users")
                .whereEqualTo("phone", userId)
                .get()
                .addOnCompleteListener(new OnCompleteListener<QuerySnapshot>() {

                    @Override
                    public void onComplete(@NonNull Task<QuerySnapshot> task) {
                        try{
                        if (task.isSuccessful()) {

                            saveToken(userId);

                            for (QueryDocumentSnapshot document : task.getResult()) {
                                if (document.getId().equalsIgnoreCase(userId)) {

                                    Intent startmainact = new Intent(EnterOTPActivity.this, MainActivity.class);
                                    startmainact.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
                                    startActivity(startmainact);
                                    finish();
                                    return;
                                }
                                //Log.d(TAG, document.getId() + " => " + document.getData());
                            }

                            Intent startposact = new Intent(EnterOTPActivity.this, ParOrStudActivity.class);

                            startposact.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
                            startActivity(startposact);
                            finish();

                        } else {
                            View parentLayout = findViewById(android.R.id.content);
                            Snackbar.make(parentLayout, "Database error: please try again", Snackbar.LENGTH_SHORT)
                                    .setAction("OKAY", new View.OnClickListener() {
                                        @Override
                                        public void onClick(View view) {

                                        }
                                    })
                                    .setActionTextColor(getResources().getColor(android.R.color.holo_red_light))
                                    .show();
                        }
                    }
                        catch(Exception e){
                            View parentLayout = findViewById(android.R.id.content);
                            Snackbar.make(parentLayout, "Database error: please try again", Snackbar.LENGTH_SHORT)
                                    .setAction("OKAY", new View.OnClickListener() {
                                        @Override
                                        public void onClick(View view) {

                                        }
                                    })
                                    .setActionTextColor(getResources().getColor(android.R.color.holo_red_light))
                                    .show();
                        }
                    }

                });
    }

    private void saveToken(final String userId) {
        FirebaseInstanceId.getInstance().getInstanceId()
                .addOnCompleteListener(new OnCompleteListener<InstanceIdResult>() {
                    @Override
                    public void onComplete(@NonNull Task<InstanceIdResult> task) {
                        if (!task.isSuccessful()) {
                            return;
                        }

                        // Get new Instance ID token
                        String token = task.getResult().getToken();
                        FirebaseFirestore.getInstance().collection("users").document(userId).update("token",token);
                    }
                });
    }

    @Override
    protected void onResume() {
        super.onResume();
        if (autoResendCount<2 && resumeCount>0) {
            sendVerificationCode(userPhoneNumber);
            autoResendCount=autoResendCount+1;
            resumeCount=resumeCount+1;
        }
    }

    @Override
    protected void onStop() {
        super.onStop();
        progressDialog.dismiss();
    }

    public void startResendTimer(int seconds) {
        timerTV.setVisibility(View.VISIBLE);
        resendOtp.setEnabled(false);

        new CountDownTimer(seconds*1000, 1000) {

            public void onTick(long millisUntilFinished) {
                String secondsString = Long.toString(millisUntilFinished/1000);
                if (millisUntilFinished<10000) {
                    secondsString = "0"+secondsString;
                }
                timerTV.setText(" (0:"+ secondsString+")");
            }

            public void onFinish() {
                resendOtp.setEnabled(true);
                timerTV.setVisibility(View.GONE);
                timerOn=false;
            }
        }.start();
    }

    @Override
    public void onBackPressed() {
        // do not allow user to go back to the screen before
    }
}

This erratic verification system delivers an incompetent UX. Is there any way to get around it?


问:
IOS: problem with triple loop
I have four array and they are full of NSNull elements: years (100 elements), months (12), days(31) and arrayString. When i choose two date I want put a string inside every array "arrayString" contained inside of every day of the period.

I choose two date and I do dateFormatter and I got first and last day, month an year:
I don't write date1 and date2 but they are two NSDate

```<code>NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:@"dd"];
int firstDay = [[dateFormatter stringFromDate:data1] intValue];
int lastDay = [[dateFormatter stringFromDate:data2] intValue];
[dateFormatter setDateFormat:@"MM"];
int firstMonth = [[dateFormatter stringFromDate:data1] intValue];
int lastMonth = [[dateFormatter stringFromDate:data2] intValue];
[dateFormatter setDateFormat:@"yyyy"];
int firstYear = [[dateFormatter stringFromDate:data1] intValue]-2011;
int lastYear = [[dateFormatter stringFromDate:data2] intValue]-2011;
NSString *string = @"firstString";
</code>```

after I want add a NSString inside every array contained in every day of the period, it is possible because every position in the arrays there are NSNull elements that I put inside in viewdidload:

```<code>for (int k = firstYear ; k<lastYear + 1; k++){

    for (int i = firstMonth; i < lastMonth+1; i++)
    {
        for (int j = firstDay; j < lastDay+1; j++)
        {
            [[days objectAtIndex:j] addObject: string];
        }

        [months replaceObjectAtIndex:i withObject:days];
    }

[years replaceObjectAtIndex:k withObject:months];
}
</code>```

This code work fine when I choose a period in the same month, because if I choose for example: 15/05/2011 to 25/05/2011 it's ok, it fill the arrays string inside every day of the period.
But if I choose for example 28/05/2011 to 1/06/2011 there is a problem in the third loop; because "firstday" is 28 and "lastday" is 1, and it don't entry inside at the loop; how can I solve this problem?

答:
Given your comments on the question, I assume that you are looking for a way of associating strings (or any object, really) with given days. This association lends itself to an NSDictionary and dates are obviously best represented with NSDate instances. With this in mind, I propose a different data structure.

Rather than deeply nested arrays, you should consider the following, wherein NSDate objects are the dictionary's keys and their respective values are NSArray instances containing the string for that specific point in time, not just the day:

```<code>NSDictionary {
    NSDate: NSString,
    NSDate: NSString,
    NSDate: ...,
}
</code>```

Now that you have your data stored in a suitable structure, you want to be able to query it for objects associated with a given day. For this, you could have the following method(s):

```<code>- (BOOL)date:(NSDate *)date isSameDayAsReferenceDate:(NSDate *)reference {
    NSCalendar *calendar = [NSCalendar currentCalendar];

    NSCalendarUnit units = NSYearCalendarUnit|NSMonthCalendarUnit|NSDayCalendarUnit;
    NSDateComponents *compDate = [calendar components:units fromDate:date];
    NSDateComponents *compReference = [calendar components:units fromDate:reference];

    return [compDate isEqual:compReference];
}

- (NSArray *)stringsForDay:(NSDate *)day withDictionary:(NSDictionary *)dictionary {
    NSSet *dates = [dictionary keysOfEntriesPassingTest:^BOOL(id key, id obj, BOOL *stop) {
        return [self date:key isSameDayAsReferenceDate:day];
    }];

    return [dictionary objectsForKeys:[dates allObjects] notFoundMarker:[NSNull null]];
}
</code>```

Now, if you wanted an array of all strings for today, you could simply call [self stringsForDay:[NSDate date] withDictionary:theDictionary] and be done with it.

This approach is more flexible than your alternative suggested in the question, as changing the granularity to weeks, months, years, etc. is now very simple.

Title: IOS: problem with triple loop

Body:
I have four array and they are full of NSNull elements: years (100 elements), months (12), days(31) and arrayString. When i choose two date I want put a string inside every array "arrayString" contained inside of every day of the period.

I choose two date and I do dateFormatter and I got first and last day, month an year:
I don't write date1 and date2 but they are two NSDate

NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:@"dd"];
int firstDay = [[dateFormatter stringFromDate:data1] intValue];
int lastDay = [[dateFormatter stringFromDate:data2] intValue];
[dateFormatter setDateFormat:@"MM"];
int firstMonth = [[dateFormatter stringFromDate:data1] intValue];
int lastMonth = [[dateFormatter stringFromDate:data2] intValue];
[dateFormatter setDateFormat:@"yyyy"];
int firstYear = [[dateFormatter stringFromDate:data1] intValue]-2011;
int lastYear = [[dateFormatter stringFromDate:data2] intValue]-2011;
NSString *string = @"firstString";

after I want add a NSString inside every array contained in every day of the period, it is possible because every position in the arrays there are NSNull elements that I put inside in viewdidload:

for (int k = firstYear ; k<lastYear + 1; k++){

    for (int i = firstMonth; i < lastMonth+1; i++)
    {
        for (int j = firstDay; j < lastDay+1; j++)
        {
            [[days objectAtIndex:j] addObject: string];
        }

        [months replaceObjectAtIndex:i withObject:days];
    }

[years replaceObjectAtIndex:k withObject:months];
}

This code work fine when I choose a period in the same month, because if I choose for example: 15/05/2011 to 25/05/2011 it's ok, it fill the arrays string inside every day of the period.
But if I choose for example 28/05/2011 to 1/06/2011 there is a problem in the third loop; because "firstday" is 28 and "lastday" is 1, and it don't entry inside at the loop; how can I solve this problem?

Body:
Given your comments on the question, I assume that you are looking for a way of associating strings (or any object, really) with given days. This association lends itself to an NSDictionary and dates are obviously best represented with NSDate instances. With this in mind, I propose a different data structure.

Rather than deeply nested arrays, you should consider the following, wherein NSDate objects are the dictionary's keys and their respective values are NSArray instances containing the string for that specific point in time, not just the day:

NSDictionary {
    NSDate: NSString,
    NSDate: NSString,
    NSDate: ...,
}

Now that you have your data stored in a suitable structure, you want to be able to query it for objects associated with a given day. For this, you could have the following method(s):

- (BOOL)date:(NSDate *)date isSameDayAsReferenceDate:(NSDate *)reference {
    NSCalendar *calendar = [NSCalendar currentCalendar];

    NSCalendarUnit units = NSYearCalendarUnit|NSMonthCalendarUnit|NSDayCalendarUnit;
    NSDateComponents *compDate = [calendar components:units fromDate:date];
    NSDateComponents *compReference = [calendar components:units fromDate:reference];

    return [compDate isEqual:compReference];
}

- (NSArray *)stringsForDay:(NSDate *)day withDictionary:(NSDictionary *)dictionary {
    NSSet *dates = [dictionary keysOfEntriesPassingTest:^BOOL(id key, id obj, BOOL *stop) {
        return [self date:key isSameDayAsReferenceDate:day];
    }];

    return [dictionary objectsForKeys:[dates allObjects] notFoundMarker:[NSNull null]];
}

Now, if you wanted an array of all strings for today, you could simply call [self stringsForDay:[NSDate date] withDictionary:theDictionary] and be done with it.

This approach is more flexible than your alternative suggested in the question, as changing the granularity to weeks, months, years, etc. is now very simple.


答:
Just use conditional aggregation:</p>

```<code>select id, label,
       sum(case when label = 'A' then 1 else 0 end) as a,
       sum(case when label = 'B' then 1 else 0 end) as b
from t
group by id, label;
</code>```

Title: Calculate distinct value_1 when value_2, value_3 is equal to certain value

Body:
The output table looks like this let's say:

table : people
+-------+-----------+-----------+
|   id  |  label    |   action  |
+-------+-----------+-----------+
|   1   |  aaaaa    |       B   |
|   1   |  aaaaa    |       B   |
|   1   |  aaaaa    |       A   |
|   2   |  aaaaa    |       B   |
|   2   |  aaaaa    |       B   |
+-------+-----------+-----------+

What I would like to do is to count unique ids this way:

table : people
+-------+-----------+-------------+-------------+
|   id  |  label    |   action_A  |   action_B  |
+-------+-----------+-------------+-------------+
|   1   |  aaaaa    |       1     |       1     |
|   2   |  aaaaa    |       0     |       1     |
+-------+-----------+-------------+-------------+

Body:
Just use conditional aggregation:

select id, label,
       sum(case when label = 'A' then 1 else 0 end) as a,
       sum(case when label = 'B' then 1 else 0 end) as b
from t
group by id, label;


问:
Search into pandas dataframe column for which input value is smaller than the next index column value
I want to search a dataframe to find a value correspond to index row and column value. However, I am struggling because the column header values are the upper bound of a range where the previous column header value is the lower bound ( but the uppper bound of its other neightbor column value).

I cannot find a way to match my input with the column corresponding to the lower bound of the range.

with an example it is very easy to see:

```<code>data_frame_test = pd.DataFrame({'location' : [1, 2, 'S'],
                                '200' : [342, 690, 103],
                                '1000' : [322, 120, 193],
                                '2000' : [249, 990, 403]})

data_frame_test = data_frame_test.set_index('location')
</code>```

and what I want to do is this

```<code>location = 1
weight = 500

output = data_frame_test.iloc[1][??] #must be equal to 342
</code>```

see, the column where weight must look into is 200, because it is in the range between ]200;1000[. I don't know what else to try to translate that into python code. Any help would be greatly appreciated.

答:
First convert columns to integers by rename if necessary:

```<code>data_frame_test = data_frame_test.set_index('location').rename(columns=int)
print (data_frame_test)
          200   1000  2000
location
1          342   322   249
2          690   120   990
S          103   193   403

weight = 500
location = 1
</code>```

And then match values by positions with DataFrame.loc with last position of True value by compare by less values like weight:

```<code>#https://stackoverflow.com/a/8768734
b = (data_frame_test.columns[::-1] < weight)
pos = len(b) - np.argmax(b) - 1
print (pos)
0

output = data_frame_test.loc[location, data_frame_test.columns[pos]]
print (output)
342
</code>```

Or you can use DataFrame.iloc with position by Index.get_loc:

```<code>output = data_frame_test.iloc[data_frame_test.index.get_loc(location), pos]
print (output)
342
</code>```

Body:
I want to search a dataframe to find a value correspond to index row and column value. However, I am struggling because the column header values are the upper bound of a range where the previous column header value is the lower bound ( but the uppper bound of its other neightbor column value).

I cannot find a way to match my input with the column corresponding to the lower bound of the range.

with an example it is very easy to see:

data_frame_test = pd.DataFrame({'location' : [1, 2, 'S'],
                                '200' : [342, 690, 103],
                                '1000' : [322, 120, 193],
                                '2000' : [249, 990, 403]})

data_frame_test = data_frame_test.set_index('location')

and what I want to do is this

location = 1
weight = 500

output = data_frame_test.iloc[1][??] #must be equal to 342

see, the column where weight must look into is 200, because it is in the range between ]200;1000[. I don't know what else to try to translate that into python code. Any help would be greatly appreciated.

Body:
First convert columns to integers by rename if necessary:

data_frame_test = data_frame_test.set_index('location').rename(columns=int)
print (data_frame_test)
          200   1000  2000
location
1          342   322   249
2          690   120   990
S          103   193   403

weight = 500
location = 1

And then match values by positions with DataFrame.loc with last position of True value by compare by less values like weight:

#https://stackoverflow.com/a/8768734
b = (data_frame_test.columns[::-1] < weight)
pos = len(b) - np.argmax(b) - 1
print (pos)
0

output = data_frame_test.loc[location, data_frame_test.columns[pos]]
print (output)
342

Or you can use DataFrame.iloc with position by Index.get_loc:

output = data_frame_test.iloc[data_frame_test.index.get_loc(location), pos]
print (output)
342


问:
Pandas : Apply function that returns multiple rows and columns
I have a DataFrame routes with the following structure :

```<code>      id                                             nodes                            traveltimes
0   id-1                                  [node-A, node-B]                                  [6.0]
1   id-2                  [node-A, node-C, node-D, node-E]                      [4.0, 80.0, 38.0]
2   id-3                                  [node-B, node-D]                                 [90.0]
3   id-4                                          [node-A]                                     []
4   id-5  [node-A, node-B, node-C, node-D, node-E, node-D]         [35.0, 30.0, 110.0, 20.0, 5.0]
..                                                 ...                                    ...
</code>```

The list of value in the nodes columns are the nodes of a graph, and the value in the traveltimes column are the time between two nodes. Each row corresponding to a route in the graph.

I want to split my routes on a threshold value of traveltimes. For example, for a threshold of 70, I want to get the following result :

```<code>      id     route_id                            nodes                            traveltimes
0     id-1          0                 [node-A, node-B]                                  [6.0]
1     id-2          0                 [node-A, node-C]                                  [4.0]
2     id-2          1                 [node-D, node-E]                                 [38.0]
3     id-3          0                         [node-B]                                     []
4     id-3          1                         [node-D]                                     []
5     id-4          0                         [node-A]                                     []
6     id-5          0         [node-A, node-B, node-C]                           [35.0, 30.0]
7     id-5          1         [node-D, node-E, node-D]                            [20.0, 5.0]
..                                                 ...                                    ...
</code>```

I made the following code that do what I want, but in an inefficient way.

I have a function that split the routes:

```<code>def split_routes(row):
    newrow = row.copy()

    threshold = 70

    nodes = newrow['nodes']
    traveltimes = newrow['traveltimes']

    rows = []
    route_id = 0
    route_nodes = []
    route_traveltimes = []

    route_nodes.append(nodes[0])

    for i in range(1, len(nodes)):
        if(traveltimes[i-1]<threshold):
            route_traveltimes.append(traveltimes[i-1])
            route_nodes.append(nodes[i])
        else :
            # Route route_id completed, starting a new one
            newrow['route_id'] = route_id
            newrow['nodes'] = route_nodes
            newrow['traveltimes'] = route_traveltimes
            rows.append(newrow)

            newrow = row.copy()
            route_nodes = []
            route_traveltimes = []
            route_id+=1
            route_nodes.append(nodes[i])

    # Route route_id completed
    newrow['route_id'] = route_id
    newrow['nodes'] = route_nodes
    newrow['traveltimes'] = route_traveltimes
    rows.append(newrow)

    df = pd.DataFrame(rows)
    return df
</code>```

And this is how I use it :

```<code>splitted_routes_array = []

for index, row in routes.iterrows():    # Inefficient loop
    splitted_routes_array.append(split_routes(row))

splitted_routes = pd.concat(splitted_routes_array).reset_index(drop=True)
</code>```

I guess I can do something way more efficient without iterating on rows by myself. But I couldn't figure out how to use apply to return multiple rows and columns at the same time.

Can someone give me some hints on that ?

答:
To explode multiple columns in pandas the only prerequisite is having same number of elements in list in all columns to be exploded. This could be done by -

```<code>def get_nodes(x):
    if(len(x)<2):
        return []
    return [[x[i], x[i+1]] for i in range(len(x)-1)]

df['nodes'] = df['nodes'].apply(lambda x: get_nodes(x))
</code>```

After this the data can be flattened using -

```<code>df = df.set_index('id').apply(lambda x: x.apply(pd.Series).stack()).reset_index().rename(columns={'level_1':'route_id'})
</code>```

To find all the routes having traveltimes greater than 70.0, we could simply do -

```<code>df[df['traveltimes']>70]
</code>```

Body:
I have a DataFrame routes with the following structure :

      id                                             nodes                            traveltimes
0   id-1                                  [node-A, node-B]                                  [6.0]
1   id-2                  [node-A, node-C, node-D, node-E]                      [4.0, 80.0, 38.0]
2   id-3                                  [node-B, node-D]                                 [90.0]
3   id-4                                          [node-A]                                     []
4   id-5  [node-A, node-B, node-C, node-D, node-E, node-D]         [35.0, 30.0, 110.0, 20.0, 5.0]
..                                                 ...                                    ...

The list of value in the nodes columns are the nodes of a graph, and the value in the traveltimes column are the time between two nodes. Each row corresponding to a route in the graph.

I want to split my routes on a threshold value of traveltimes. For example, for a threshold of 70, I want to get the following result :

      id     route_id                            nodes                            traveltimes
0     id-1          0                 [node-A, node-B]                                  [6.0]
1     id-2          0                 [node-A, node-C]                                  [4.0]
2     id-2          1                 [node-D, node-E]                                 [38.0]
3     id-3          0                         [node-B]                                     []
4     id-3          1                         [node-D]                                     []
5     id-4          0                         [node-A]                                     []
6     id-5          0         [node-A, node-B, node-C]                           [35.0, 30.0]
7     id-5          1         [node-D, node-E, node-D]                            [20.0, 5.0]
..                                                 ...                                    ...

I made the following code that do what I want, but in an inefficient way.

I have a function that split the routes:

def split_routes(row):
    newrow = row.copy()

    threshold = 70

    nodes = newrow['nodes']
    traveltimes = newrow['traveltimes']

    rows = []
    route_id = 0
    route_nodes = []
    route_traveltimes = []

    route_nodes.append(nodes[0])

    for i in range(1, len(nodes)):
        if(traveltimes[i-1]<threshold):
            route_traveltimes.append(traveltimes[i-1])
            route_nodes.append(nodes[i])
        else :
            # Route route_id completed, starting a new one
            newrow['route_id'] = route_id
            newrow['nodes'] = route_nodes
            newrow['traveltimes'] = route_traveltimes
            rows.append(newrow)

            newrow = row.copy()
            route_nodes = []
            route_traveltimes = []
            route_id+=1
            route_nodes.append(nodes[i])

    # Route route_id completed
    newrow['route_id'] = route_id
    newrow['nodes'] = route_nodes
    newrow['traveltimes'] = route_traveltimes
    rows.append(newrow)

    df = pd.DataFrame(rows)
    return df

And this is how I use it :

splitted_routes_array = []

for index, row in routes.iterrows():    # Inefficient loop
    splitted_routes_array.append(split_routes(row))

splitted_routes = pd.concat(splitted_routes_array).reset_index(drop=True)

I guess I can do something way more efficient without iterating on rows by myself. But I couldn't figure out how to use apply to return multiple rows and columns at the same time.

Can someone give me some hints on that ?

Body:
To explode multiple columns in pandas the only prerequisite is having same number of elements in list in all columns to be exploded. This could be done by -

def get_nodes(x):
    if(len(x)<2):
        return []
    return [[x[i], x[i+1]] for i in range(len(x)-1)]

df['nodes'] = df['nodes'].apply(lambda x: get_nodes(x))

After this the data can be flattened using -

df = df.set_index('id').apply(lambda x: x.apply(pd.Series).stack()).reset_index().rename(columns={'level_1':'route_id'})

To find all the routes having traveltimes greater than 70.0, we could simply do -

df[df['traveltimes']>70]


问:
Symfony 2 Twitter and Facebook API
Are there good plugins for Symfony 2 to connect to the Twitter and Facebook API to receive data and interact with a user?</p>

答:
Note: both bundles below have been deprecated in favour of HWIOAuthBundle.

Facebook Bundle

Twitter Bundle

A good resource for symfony2 bundles (plugins) is: knpBundles

Title: Symfony 2 Twitter and Facebook API


问:
Using two python functions boto3 in a single AWS Lambda
I want to write two functions in a single AWS Lambda function. currently, Lambda triggers the function using the handler in case I have two functions in my code then how to change it so that the Lambda handler can execute both the functions.

I have found this. However, it is using if statement. In my scenario I will have to run both the functions one after the other and also pass the output of 1st function to the 2nd function. Thanks
How to have more than one handler in AWS Lambda Function?

Here is the sample code:

```<code>import boto3' import json' from datetime
import datetime REGION = 'us-east-1'
emrclient = boto3.client('emr', region_name=REGION)

def lambda_handler(event, context):
EMRS = emrclient.list_clusters( ClusterStates = ['STARTING', 'RUNNING', 'WAITING', 'TERMINATING'] )
clusters = EMRS["Clusters"]
    for cluster in clusters :
    ID = cluster.get("Id")
    EMRid = emrclient.list_instance_groups( ClusterId = str("ID") )
    print(EMRid)
</code>```

答:
You don't need an additional function to achieve what you have listed as an example. That said, assuming that you need to add additional processing/functionality on the instance_groups dict, you can start here. This should work, if you have 50 clusters or less:

import boto3
import json
import datetime

emrclient = boto3.client('emr', region_name='us-east-1')

def lambda_handler(event, context):
    EMRS = emrclient.list_clusters(ClusterStates=['STARTING', 'RUNNING', 'WAITING', 'TERMINATING'])
    for cluster in EMRS['Clusters']:
        emr_inst_grp_work(cluster['Id'])

def emr_inst_grp_work(cluster_id):
    """Get instance group details dict for given cluster id"""
    inst_dict = emrclient.list_instance_groups(ClusterId = cluster_id)
    print(inst_dict)
    # ADD code for additional dict or cluster work/processing here

```

Body:
I want to write two functions in a single AWS Lambda function. currently, Lambda triggers the function using the handler in case I have two functions in my code then how to change it so that the Lambda handler can execute both the functions.

I have found this. However, it is using if statement. In my scenario I will have to run both the functions one after the other and also pass the output of 1st function to the 2nd function. Thanks
How to have more than one handler in AWS Lambda Function?

Here is the sample code:

import boto3' import json' from datetime
import datetime REGION = 'us-east-1'
emrclient = boto3.client('emr', region_name=REGION)

def lambda_handler(event, context):
EMRS = emrclient.list_clusters( ClusterStates = ['STARTING', 'RUNNING', 'WAITING', 'TERMINATING'] )
clusters = EMRS["Clusters"]
    for cluster in clusters :
    ID = cluster.get("Id")
    EMRid = emrclient.list_instance_groups( ClusterId = str("ID") )
    print(EMRid)


问:
How to take depth of neural network as argument while constructing Network in Pytorch
I have written following code to take depth of network as parameter in Pytorch.
Later I realized even if I am using many hidden layers, the learnable parameters remain the same. </p>

```<code>class Net3(torch.nn.Module):
    def __init__(self, n_feature, n_hidden, n_output, depth, init):
        super(Net3, self).__init__()
        self.input = torch.nn.Linear(n_feature, n_hidden).float().to(device)
        self.hidden = torch.nn.Linear(n_hidden, n_hidden).float().to(device)
        self.predict = torch.nn.Linear(n_hidden, n_output).float().to(device)   =
        self.depth = depth

    def forward(self, x):
        x = F.relu(self.input(x))      # activation function for hidden layer
        for i in range(self.depth):
           x = F.relu(self.hidden(x))      # activation function for hidden layer
        x = self.predict(x)
        return x
</code>```

<p>Is there any other way to achieve this ? </p>

答:
In init you need to create multiple hidden layers, currently you're only making one. One possibility to do this with little overhead is using a torch.nn.ModuleDict that will give you named layers:

```<code>class Net3(torch.nn.Module):
    def __init__(self, n_feature, n_hidden, n_output, depth, init):
        super(Net3, self).__init__()
        self.layers = nn.ModuleDict() # a collection that will hold your layers

        self.layers['input'] = torch.nn.Linear(n_feature, n_hidden).float().to(device)

        for i in range(1, depth):
            self.layers['hidden_'+str(i)] = torch.nn.Linear(n_hidden, n_hidden).float().to(device)

        self.layers['output'] = torch.nn.Linear(n_hidden, n_output).float().to(device)   =
        self.depth = depth

    def forward(self, x):
        for layer in self.layers:
            x = F.relu(self.layers[layer](x))

        return x
</code>```

Body:
I have written following code to take depth of network as parameter in Pytorch.
Later I realized even if I am using many hidden layers, the learnable parameters remain the same.

class Net3(torch.nn.Module):
    def __init__(self, n_feature, n_hidden, n_output, depth, init):
        super(Net3, self).__init__()
        self.input = torch.nn.Linear(n_feature, n_hidden).float().to(device)
        self.hidden = torch.nn.Linear(n_hidden, n_hidden).float().to(device)
        self.predict = torch.nn.Linear(n_hidden, n_output).float().to(device)   =
        self.depth = depth

    def forward(self, x):
        x = F.relu(self.input(x))      # activation function for hidden layer
        for i in range(self.depth):
           x = F.relu(self.hidden(x))      # activation function for hidden layer
        x = self.predict(x)
        return x

Is there any other way to achieve this ?

Body:
In init you need to create multiple hidden layers, currently you're only making one. One possibility to do this with little overhead is using a torch.nn.ModuleDict that will give you named layers:

class Net3(torch.nn.Module):
    def __init__(self, n_feature, n_hidden, n_output, depth, init):
        super(Net3, self).__init__()
        self.layers = nn.ModuleDict() # a collection that will hold your layers

        self.layers['input'] = torch.nn.Linear(n_feature, n_hidden).float().to(device)

        for i in range(1, depth):
            self.layers['hidden_'+str(i)] = torch.nn.Linear(n_hidden, n_hidden).float().to(device)

        self.layers['output'] = torch.nn.Linear(n_hidden, n_output).float().to(device)   =
        self.depth = depth

    def forward(self, x):
        for layer in self.layers:
            x = F.relu(self.layers[layer](x))

        return x