问:
External View query works in athena console but fails to work when using it in aws quicksight
I am using cloudformation to create a "Virtual_View" of my table. When I use the same view to query data in AWS Athena Console it works fine and returns the data but When I try to use the same view as a dataset in AWS QuickSight(using SPICE) it throws following error:

```<code>"Unable to prepare this table.
Please try again or choose another table."
</code>```

If I choose to run it using "Query" in Quicksight I get following error:

```<code>region: us-east-1
timestamp:  1558718487000
requestId:  58e18321-7e48-11e9-9740-618021a5eae5
sourceErrorCode:    0
sourceErrorMessage: [Simba][JDBC](11380) Null pointer exception.
sourceErrorState:   HY000
sourceException:    java.sql.SQLException
sourceType: ATHENA
</code>```

Funny part is If I modify my view by using "show/edit query" option in Athena Web Interface and run the "Alter" view command against my view without changing anything .. it starts working fine on quick sight.  this leads me to believe that the creation of View using my cloud formation is missing something or perhaps some thing else? Here is my cloudformation template that I am using to create db + table + view.

```<code>AWSTemplateFormatVersion: 2010-09-09
Description: Glue Athena database and table configuration

Parameters:
  Stage:
    Description: Stage name (dev, prod)
    Type: String
    MinLength: 3
  PartitionKey:
    Description: Patition key for the table (dont use dashes)
    Type: String
    Default: "modkey"
    MinLength: 3

Resources:
  GlueDatabase:
    Type: AWS::Glue::Database
    Properties:
      DatabaseInput:
        Name: !Sub
          - db_${Stage}_glue
          -
            Stage: !Ref Stage
      CatalogId: !Ref AWS::AccountId

  GlueTable:
    Type: AWS::Glue::Table
    Properties:
      DatabaseName: !Ref GlueDatabase
      CatalogId: !Ref AWS::AccountId
      TableInput:
        Name: tbl_request
        TableType: EXTERNAL_TABLE
        Parameters:
          CrawlerSchemaDeserializerVersion: "1.0"
          CrawlerSchemaSerializerVersion: "1.0"
          classification: json
          compressionType: none
          typeOfData: file
        PartitionKeys:
        # Data is partitioned by this key
        - Name: !Ref PartitionKey
          Type: string
        StorageDescriptor:
          Compressed: false
          Location:
            Fn::Join:
              - ''
              - - 's3://'
                - Fn::ImportValue:
                    !Sub
                      - requests-${Stage}-s3
                      -
                        Stage: !Ref Stage
                - '/'
          InputFormat: org.apache.hadoop.mapred.TextInputFormat
          StoredAsSubDirectories: false
          OutputFormat: org.apache.hadoop.hive.ql.io.HiveIgnoreKeyTextOutputFormat
          SerdeInfo:
            Parameters: {paths: 'Id,Module,Organization,Redirect,RequestTime,Suppressed,Template,TemplateData,ToAddresses,ToAddress,Events'}
            SerializationLibrary: org.openx.data.jsonserde.JsonSerDe
          Columns:
          - {Name: id, Type: string}
          - {Name: organization, Type: string}
          - {Name: module, Type: string}
          - {Name: requesttime, Type: string}
          - {Name: templatedata, Type: string}
          - {Name: template, Type: string}
          - {Name: toaddress, Type: string}
          - {Name: toaddresses, Type: array<string>}
          - {Name: suppressed, Type: array<string>}
          - {Name: events, Type: array<string>}
          - {Name: redirect, Type: array<string>}

  ViewDeliverySample:
    Type: AWS::Glue::Table
    DependsOn: GlueTable
    Properties:
      DatabaseName: !Ref GlueDatabase
      CatalogId: !Ref AWS::AccountId
      TableInput:
        Name: tbl_request_view
        TableType: VIRTUAL_VIEW
        ViewOriginalText:
          Fn::Join:
            - ''
            - - '/* Presto View: '
              - Fn::Base64: !Sub
                  - |
                      {
                      "originalSql": "WITH dataset AS ( WITH requests_dataset AS (SELECT * FROM ${TableName} ), basedataset AS (SELECT id, module, ${PartitionKey}, CAST( json_extract(event, '$.eventtype') AS VARCHAR ) AS eventtype, event AS detail FROM requests_dataset CROSS JOIN unnest(events) AS t(event) ), send_dataset AS (SELECT email, module, ${PartitionKey}, eventtype, CAST(json_extract(detail, '$.mail.timestamp') AS VARCHAR ) AS time, id FROM basedataset CROSS JOIN unnest (CAST(json_extract(detail,'$.mail.destination') AS ARRAY(VARCHAR))) AS t(email) WHERE eventtype = 'Send' ), delivery_dataset AS (SELECT email, module, ${PartitionKey}, eventtype, CAST(json_extract(detail, '$.delivery.timestamp') AS VARCHAR ) AS time, id FROM basedataset CROSS JOIN unnest (CAST(json_extract(detail,'$.delivery.recipients') AS ARRAY(VARCHAR))) AS t(email) WHERE eventtype = 'Delivery' ), bounce_dataset AS (SELECT CAST(rr['emailaddress'] AS VARCHAR )as email, module,${PartitionKey}, eventtype, CAST(json_extract(detail,'$.bounce.timestamp') AS VARCHAR ) AS time, id FROM basedataset CROSS JOIN unnest (CAST(json_extract(detail,'$.bounce.bouncedrecipients') AS ARRAY(MAP(VARCHAR,JSON))) ) AS t(rr) WHERE eventtype='Bounce' ), suppress_dataset AS (SELECT email, module, ${PartitionKey}, 'suppress' AS eventtype, requesttime AS time, id FROM requests_dataset CROSS JOIN unnest(suppressed) AS t(email) ) SELECT * FROM send_dataset UNION SELECT * FROM delivery_dataset UNION SELECT * FROM bounce_dataset UNION SELECT * FROM suppress_dataset ) SELECT * FROM dataset ORDER BY email, module, eventtype, time",
                      "catalog": "awsdatacatalog",
                      "schema": "${DatabaseName}",
                      "columns": [
                        {
                          "name": "email",
                          "type": "varchar"
                        },
                        {
                          "name": "module",
                          "type": "varchar"
                        },
                        {
                          "name": "modkey",
                          "type": "varchar"
                        },
                        {
                          "name": "eventtype",
                          "type": "varchar"
                        },
                        {
                          "name": "time",
                          "type": "varchar"
                        },
                        {
                          "name": "id",
                          "type": "varchar"
                        }
                      ]
                      }
                  - {
                      DatabaseName: !Ref GlueDatabase,
                      TableName: !Ref GlueTable,
                      PartitionKey: !Ref PartitionKey
                    }
              - ' */'
        ViewExpandedText: '/* Presto View */'
        Parameters:
          presto_view: true
          comment: "Presto View"
        StorageDescriptor:
          Compressed: false
          StoredAsSubDirectories: false
          SerdeInfo:
            Parameters: {paths: 'email,module,modkey,eventtype,time,id'}
            SerializationLibrary: org.openx.data.jsonserde.JsonSerDe
          Columns:
          - {Name: email, Type: string}
          - {Name: module, Type: string}
          - {Name: modkey, Type: string}
          - {Name: eventtype, Type: string}
          - {Name: time, Type: string}
          - {Name: id, Type: string}
</code>```

答:
able to fix by taking out serdeinfo and adding empty partitionkey array.</p>

```<code>ViewDeliverySample:
    Description: some description here  # change this
    Type: AWS::Glue::Table
    DependsOn: GlueTable
    Properties:
      DatabaseName: !Ref GlueDatabase
      CatalogId: !Ref AWS::AccountId
      TableInput:
        Name: tbl_request_view
        TableType: VIRTUAL_VIEW
        Parameters:
          presto_view: true
        PartitionKeys: []
        ViewOriginalText:
          Fn::Join:
            - ''
            - - '/* Presto View: '
              - Fn::Base64: !Sub
                  - |
                      {
                      "originalSql": "my sql query here",
                      "catalog": "awsdatacatalog",
                      "schema": "${DatabaseName}",
                      "columns": [
                        {
                          "name": "email",
                          "type": "varchar"
                        },
                        {
                          "name": "module",
                          "type": "varchar"
                        },
                        {
                          "name": "${PartitionKey}",
                          "type": "varchar"
                        },
                        {
                          "name": "eventtype",
                          "type": "varchar"
                        },
                        {
                          "name": "time",
                          "type": "varchar"
                        },
                        {
                          "name": "id",
                          "type": "varchar"
                        }
                      ]
                      }
                  - {
                      DatabaseName: !Ref GlueDatabase,
                      TableName: !Ref GlueTable,
                      PartitionKey: !Ref PartitionKey
                    }
              - ' */'
        ViewExpandedText: '/* Presto View */'
        StorageDescriptor:
          SerdeInfo: {}
          Columns:
          - {Name: email, Type: string}
          - {Name: module, Type: string}
          - {Name: eventtype, Type: string}
          - {Name: time, Type: string}
          - {Name: id, Type: string}
</code>```

Body:
I am using cloudformation to create a "Virtual_View" of my table. When I use the same view to query data in AWS Athena Console it works fine and returns the data but When I try to use the same view as a dataset in AWS QuickSight(using SPICE) it throws following error:

"Unable to prepare this table.
Please try again or choose another table."

If I choose to run it using "Query" in Quicksight I get following error:

region: us-east-1
timestamp:  1558718487000
requestId:  58e18321-7e48-11e9-9740-618021a5eae5
sourceErrorCode:    0
sourceErrorMessage: [Simba][JDBC](11380) Null pointer exception.
sourceErrorState:   HY000
sourceException:    java.sql.SQLException
sourceType: ATHENA

Funny part is If I modify my view by using "show/edit query" option in Athena Web Interface and run the "Alter" view command against my view without changing anything .. it starts working fine on quick sight.  this leads me to believe that the creation of View using my cloud formation is missing something or perhaps some thing else? Here is my cloudformation template that I am using to create db + table + view.

AWSTemplateFormatVersion: 2010-09-09
Description: Glue Athena database and table configuration

Parameters:
  Stage:
    Description: Stage name (dev, prod)
    Type: String
    MinLength: 3
  PartitionKey:
    Description: Patition key for the table (dont use dashes)
    Type: String
    Default: "modkey"
    MinLength: 3

Resources:
  GlueDatabase:
    Type: AWS::Glue::Database
    Properties:
      DatabaseInput:
        Name: !Sub
          - db_${Stage}_glue
          -
            Stage: !Ref Stage
      CatalogId: !Ref AWS::AccountId

  GlueTable:
    Type: AWS::Glue::Table
    Properties:
      DatabaseName: !Ref GlueDatabase
      CatalogId: !Ref AWS::AccountId
      TableInput:
        Name: tbl_request
        TableType: EXTERNAL_TABLE
        Parameters:
          CrawlerSchemaDeserializerVersion: "1.0"
          CrawlerSchemaSerializerVersion: "1.0"
          classification: json
          compressionType: none
          typeOfData: file
        PartitionKeys:
        # Data is partitioned by this key
        - Name: !Ref PartitionKey
          Type: string
        StorageDescriptor:
          Compressed: false
          Location:
            Fn::Join:
              - ''
              - - 's3://'
                - Fn::ImportValue:
                    !Sub
                      - requests-${Stage}-s3
                      -
                        Stage: !Ref Stage
                - '/'
          InputFormat: org.apache.hadoop.mapred.TextInputFormat
          StoredAsSubDirectories: false
          OutputFormat: org.apache.hadoop.hive.ql.io.HiveIgnoreKeyTextOutputFormat
          SerdeInfo:
            Parameters: {paths: 'Id,Module,Organization,Redirect,RequestTime,Suppressed,Template,TemplateData,ToAddresses,ToAddress,Events'}
            SerializationLibrary: org.openx.data.jsonserde.JsonSerDe
          Columns:
          - {Name: id, Type: string}
          - {Name: organization, Type: string}
          - {Name: module, Type: string}
          - {Name: requesttime, Type: string}
          - {Name: templatedata, Type: string}
          - {Name: template, Type: string}
          - {Name: toaddress, Type: string}
          - {Name: toaddresses, Type: array<string>}
          - {Name: suppressed, Type: array<string>}
          - {Name: events, Type: array<string>}
          - {Name: redirect, Type: array<string>}

  ViewDeliverySample:
    Type: AWS::Glue::Table
    DependsOn: GlueTable
    Properties:
      DatabaseName: !Ref GlueDatabase
      CatalogId: !Ref AWS::AccountId
      TableInput:
        Name: tbl_request_view
        TableType: VIRTUAL_VIEW
        ViewOriginalText:
          Fn::Join:
            - ''
            - - '/* Presto View: '
              - Fn::Base64: !Sub
                  - |
                      {
                      "originalSql": "WITH dataset AS ( WITH requests_dataset AS (SELECT * FROM ${TableName} ), basedataset AS (SELECT id, module, ${PartitionKey}, CAST( json_extract(event, '$.eventtype') AS VARCHAR ) AS eventtype, event AS detail FROM requests_dataset CROSS JOIN unnest(events) AS t(event) ), send_dataset AS (SELECT email, module, ${PartitionKey}, eventtype, CAST(json_extract(detail, '$.mail.timestamp') AS VARCHAR ) AS time, id FROM basedataset CROSS JOIN unnest (CAST(json_extract(detail,'$.mail.destination') AS ARRAY(VARCHAR))) AS t(email) WHERE eventtype = 'Send' ), delivery_dataset AS (SELECT email, module, ${PartitionKey}, eventtype, CAST(json_extract(detail, '$.delivery.timestamp') AS VARCHAR ) AS time, id FROM basedataset CROSS JOIN unnest (CAST(json_extract(detail,'$.delivery.recipients') AS ARRAY(VARCHAR))) AS t(email) WHERE eventtype = 'Delivery' ), bounce_dataset AS (SELECT CAST(rr['emailaddress'] AS VARCHAR )as email, module,${PartitionKey}, eventtype, CAST(json_extract(detail,'$.bounce.timestamp') AS VARCHAR ) AS time, id FROM basedataset CROSS JOIN unnest (CAST(json_extract(detail,'$.bounce.bouncedrecipients') AS ARRAY(MAP(VARCHAR,JSON))) ) AS t(rr) WHERE eventtype='Bounce' ), suppress_dataset AS (SELECT email, module, ${PartitionKey}, 'suppress' AS eventtype, requesttime AS time, id FROM requests_dataset CROSS JOIN unnest(suppressed) AS t(email) ) SELECT * FROM send_dataset UNION SELECT * FROM delivery_dataset UNION SELECT * FROM bounce_dataset UNION SELECT * FROM suppress_dataset ) SELECT * FROM dataset ORDER BY email, module, eventtype, time",
                      "catalog": "awsdatacatalog",
                      "schema": "${DatabaseName}",
                      "columns": [
                        {
                          "name": "email",
                          "type": "varchar"
                        },
                        {
                          "name": "module",
                          "type": "varchar"
                        },
                        {
                          "name": "modkey",
                          "type": "varchar"
                        },
                        {
                          "name": "eventtype",
                          "type": "varchar"
                        },
                        {
                          "name": "time",
                          "type": "varchar"
                        },
                        {
                          "name": "id",
                          "type": "varchar"
                        }
                      ]
                      }
                  - {
                      DatabaseName: !Ref GlueDatabase,
                      TableName: !Ref GlueTable,
                      PartitionKey: !Ref PartitionKey
                    }
              - ' */'
        ViewExpandedText: '/* Presto View */'
        Parameters:
          presto_view: true
          comment: "Presto View"
        StorageDescriptor:
          Compressed: false
          StoredAsSubDirectories: false
          SerdeInfo:
            Parameters: {paths: 'email,module,modkey,eventtype,time,id'}
            SerializationLibrary: org.openx.data.jsonserde.JsonSerDe
          Columns:
          - {Name: email, Type: string}
          - {Name: module, Type: string}
          - {Name: modkey, Type: string}
          - {Name: eventtype, Type: string}
          - {Name: time, Type: string}
          - {Name: id, Type: string}

Body:
able to fix by taking out serdeinfo and adding empty partitionkey array.

ViewDeliverySample:
    Description: some description here  # change this
    Type: AWS::Glue::Table
    DependsOn: GlueTable
    Properties:
      DatabaseName: !Ref GlueDatabase
      CatalogId: !Ref AWS::AccountId
      TableInput:
        Name: tbl_request_view
        TableType: VIRTUAL_VIEW
        Parameters:
          presto_view: true
        PartitionKeys: []
        ViewOriginalText:
          Fn::Join:
            - ''
            - - '/* Presto View: '
              - Fn::Base64: !Sub
                  - |
                      {
                      "originalSql": "my sql query here",
                      "catalog": "awsdatacatalog",
                      "schema": "${DatabaseName}",
                      "columns": [
                        {
                          "name": "email",
                          "type": "varchar"
                        },
                        {
                          "name": "module",
                          "type": "varchar"
                        },
                        {
                          "name": "${PartitionKey}",
                          "type": "varchar"
                        },
                        {
                          "name": "eventtype",
                          "type": "varchar"
                        },
                        {
                          "name": "time",
                          "type": "varchar"
                        },
                        {
                          "name": "id",
                          "type": "varchar"
                        }
                      ]
                      }
                  - {
                      DatabaseName: !Ref GlueDatabase,
                      TableName: !Ref GlueTable,
                      PartitionKey: !Ref PartitionKey
                    }
              - ' */'
        ViewExpandedText: '/* Presto View */'
        StorageDescriptor:
          SerdeInfo: {}
          Columns:
          - {Name: email, Type: string}
          - {Name: module, Type: string}
          - {Name: eventtype, Type: string}
          - {Name: time, Type: string}
          - {Name: id, Type: string}


来源: stackexchange

问:
Can I use the same adapter for two different listviews in different activities?
I want to set two activities with one listview on each. To do it i've designed my own xml file for it's design, and so the listview has different textviews and images. But i'd like to use the same adapter on both listviews.

That's my java file of the carnes activity.

```<code>public class Carnes extends AppCompatActivity {
    private ListView lvItems;
    private Adapter adaptador;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_carnes);

        lvItems = (ListView) findViewById(R.id.lv_carnes);
        adaptador = (Adapter) new Adaptador(this, GetArrayItems());
        lvItems.setAdapter((ListAdapter) adaptador);
    }

    private ArrayList<Entidad> GetArrayItems() {
        ArrayList<Entidad> listItems = new ArrayList<>();
        listItems.add(new Entidad(R.drawable.calabacines_3, "Lomo", " 5 min.", 5, R.drawable.color_carnes));
        listItems.add(new Entidad(R.drawable.patatas_deluxe_especiadas_70523_300_150, "Pollo", " 20 min.", 4, R.drawable.color_carnes));
        listItems.add(new Entidad(R.drawable.tomate, "Pavo", " 1 min.", 3, R.drawable.color_carnes));

        return listItems;
    }
}
</code>```

Here it is my Adapter:

```<code>public class Adaptador extends BaseAdapter {
    private Context context;
    private ArrayList<Entidad> listItems;

    public Adaptador(Context context, ArrayList<Entidad> listItems) {
        this.context = context;
        this.listItems = listItems;
    }

    @Override
    public int getCount() {
        return listItems.size();
    }

    @Override
    public Object getItem(int position) {
        return listItems.get(position);
    }

    @Override
    public long getItemId(int position) {
        return 0;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        Entidad Item = (Entidad) getItem(position);

        convertView = LayoutInflater.from(context).inflate(R.layout.elemento_lista, null);
        ImageView imgFoto = (ImageView) convertView.findViewById(R.id.imgFoto);
        TextView tvTitulo = (TextView) convertView.findViewById(R.id.tvTitulo);
        TextView tvTiempo = (TextView) convertView.findViewById(R.id.tvTiempo);
        RatingBar calificacion = (RatingBar) convertView.findViewById(R.id.ratingBarVerd);
        ImageView colorfondo = (ImageView) convertView.findViewById(R.id.colorfondo);

        imgFoto.setImageResource(Item.getImgFoto());
        tvTitulo.setText(Item.getTitulo());
        tvTiempo.setText(Item.getTiempo());
        calificacion.setRating(Item.getRating());
        colorfondo.setImageResource(Item.getColorfondo());

        return convertView;
    }
}
</code>```

And i leave you the other activity which uses the same Adapter below (remember it's a different listview):

```<code>public class Verduras extends AppCompatActivity {
    private ListView lvItems;
    private Adapter adaptador;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_verduras);

        lvItems = (ListView) findViewById(R.id.lv_verduras);
        adaptador = (Adapter) new Adaptador(this, GetArrayItems());
        lvItems.setAdapter((ListAdapter) adaptador);
    }

    private ArrayList<Entidad> GetArrayItems() {
        ArrayList<Entidad> listItems = new ArrayList<>();
        listItems.add(new Entidad(R.drawable.calabacines_3, "Calabacines", " 10 min.", 4, R.drawable.color_verduras));
        listItems.add(new Entidad(R.drawable.patatas_deluxe_especiadas_70523_300_150, "Patatas", " 15 min.", 2, R.drawable.color_verduras));
        listItems.add(new Entidad(R.drawable.tomate, "Tomates", " 2 min.", 5, R.drawable.color_verduras));

        return listItems;
    }
}
</code>```

And that's what i've used to define the variables:

```<code>public class Entidad {

    private int imgFoto;
    private String titulo;
    private String tiempo;
    private int ratingBar;
    private int colorfondo;

    public Entidad(int imgFoto, String titulo, String tiempo, int ratingBar, int colorfondo) {

        this.imgFoto = imgFoto;
        this.titulo = titulo;
        this.tiempo = tiempo;
        this.ratingBar = ratingBar;
        this.colorfondo = colorfondo;
    }

    public int getImgFoto() {
        return imgFoto;
    }

    public String getTitulo() {
        return titulo;
    }

    public String getTiempo() {
        return tiempo;
    }

    public int getRating() { return ratingBar; }

    public int getColorfondo() {
        return colorfondo;
    }
}
</code>```

What it happens is that the code looks like it's OK, but when you run the app, then it suddenly stops without telling you what happende.

Thanks for helping and if you need anything else just tell me.

That's what appears onthe logcat.

```<code>05-29 16:08:38.173 2247-2247/com.test.platos4 E/AndroidRuntime: FATAL EXCEPTION: main
    android.content.res.Resources$NotFoundException: Resource ID #0x7f060059
        at android.content.res.Resources.getValue(Resources.java:1013)
        at android.support.v7.widget.ResourcesWrapper.getValue(ResourcesWrapper.java:209)
        at android.support.v7.widget.AppCompatDrawableManager.loadDrawableFromDelegates(AppCompatDrawableManager.java:331)
        at android.support.v7.widget.AppCompatDrawableManager.getDrawable(AppCompatDrawableManager.java:198)
        at android.support.v7.widget.AppCompatDrawableManager.getDrawable(AppCompatDrawableManager.java:191)
        at android.support.v7.content.res.AppCompatResources.getDrawable(AppCompatResources.java:102)
        at android.support.v7.widget.AppCompatImageHelper.setImageResource(AppCompatImageHelper.java:86)
        at android.support.v7.widget.AppCompatImageView.setImageResource(AppCompatImageView.java:94)
        at com.test.platos4.Adaptador.getView(Adaptador.java:62)
        at android.widget.AbsListView.obtainView(AbsListView.java:2271)
        at android.widget.ListView.makeAndAddView(ListView.java:1769)
        at android.widget.ListView.fillDown(ListView.java:672)
        at android.widget.ListView.fillFromTop(ListView.java:733)
        at android.widget.ListView.layoutChildren(ListView.java:1622)
        at android.widget.AbsListView.onLayout(AbsListView.java:2106)
        at android.view.View.layout(View.java:13754)
        at android.view.ViewGroup.layout(ViewGroup.java:4364)
        at android.widget.RelativeLayout.onLayout(RelativeLayout.java:948)
        at android.view.View.layout(View.java:13754)
        at android.view.ViewGroup.layout(ViewGroup.java:4364)
        at android.widget.FrameLayout.onLayout(FrameLayout.java:448)
        at android.view.View.layout(View.java:13754)
        at android.view.ViewGroup.layout(ViewGroup.java:4364)
        at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1649)
        at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1507)
        at android.widget.LinearLayout.onLayout(LinearLayout.java:1420)
        at android.view.View.layout(View.java:13754)
        at android.view.ViewGroup.layout(ViewGroup.java:4364)
        at android.widget.FrameLayout.onLayout(FrameLayout.java:448)
        at android.view.View.layout(View.java:13754)
        at android.view.ViewGroup.layout(ViewGroup.java:4364)
        at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1649)
        at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1507)
        at android.widget.LinearLayout.onLayout(LinearLayout.java:1420)
        at android.view.View.layout(View.java:13754)
        at android.view.ViewGroup.layout(ViewGroup.java:4364)
        at android.widget.FrameLayout.onLayout(FrameLayout.java:448)
        at android.view.View.layout(View.java:13754)
        at android.view.ViewGroup.layout(ViewGroup.java:4364)
        at android.view.ViewRootImpl.performLayout(ViewRootImpl.java:1868)
        at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:1689)
        at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1000)
        at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:4214)
        at android.view.Choreographer$CallbackRecord.run(Choreographer.java:725)
        at android.view.Choreographer.doCallbacks(Choreographer.java:555)
        at android.view.Choreographer.doFrame(Choreographer.java:525)
        at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:711)
        at android.os.Handler.handleCallback(Handler.java:615)
        at android.os.Handler.dispatchMessage(Handler.java:92)
        at android.os.Looper.loop(Looper.java:137)
        at android.app.ActivityThread.main(ActivityThread.java:4745)
        at java.lang.reflect.Method.invokeNative(Native Method)
        at java.lang.reflect.Method.invoke(Method.java:511)
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:786)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553)
        at dalvik.system.NativeStart.main(Native Method)
05-29 16:08:38.183 1379-1571/system_process W/ActivityManager:   Force finishing activity com.test.platos4/.Carnes
05-29 16:08:38.323 1379-1571/system_process D/dalvikvm: GC_FOR_ALLOC freed 658K, 12% free 22447K/25415K, paused 19ms, total 19ms
05-29 16:08:38.323 1379-1571/system_process W/ActivityManager:   Force finishing activity com.test.platos4/.Dishes
05-29 16:08:38.413 1121-1621/? D/gralloc_ranchu: gralloc_alloc: Creating ashmem region of size 1114112
05-29 16:08:38.853 1379-1392/system_process W/ActivityManager: Activity pause timeout for ActivityRecord{a78e7c78 com.test.platos4/.Carnes}
05-29 16:08:39.403 1121-1456/? D/gralloc_ranchu: gralloc_alloc: Creating ashmem region of size 1114112
05-29 16:08:39.663 1121-1456/? D/gralloc_ranchu: gralloc_alloc: Creating ashmem region of size 1114112
05-29 16:08:48.043 1379-1392/system_process W/ActivityManager: Launch timeout has expired, giving up wake lock!
    Activity idle timeout for ActivityRecord{a78e7c78 com.test.platos4/.Carnes}
05-29 16:08:48.863 1379-1392/system_process W/ActivityManager: Activity idle timeout for ActivityRecord{a7ce95d0 com.test.platos4/.Menu}
05-29 16:08:58.043 1379-1392/system_process W/ActivityManager: Activity destroy timeout for ActivityRecord{a7ce7888 com.test.platos4/.Dishes}
    Activity destroy timeout for ActivityRecord{a78e7c78 com.test.platos4/.Carnes}
05-29 16:09:00.013 1440-1440/com.android.systemui D/EGL_emulation: eglMakeCurrent: 0xb8af20d0: ver 2 0
</code>```

答:
In your code your not using the same adapter, you are instantiating a new adapter in both your Activities like: new Adaptador(...)

Here´s a tutorial on Using a BaseAdapter with ListView,

Here´s a snipe from the tutorial showing how getView() should work:

```<code>@Override
    public View getView(int position, View convertView, ViewGroup parent) {
        // inflate the layout for each list row
        if (convertView == null) {
            convertView = LayoutInflater.from(context).
                inflate(R.layout.layout_list_view_row_items, parent, false);
        }

        // get current item to be displayed
        Item currentItem = (Item) getItem(position);

        // get the TextView for item name and item description
        TextView textViewItemName = (TextView)
            convertView.findViewById(R.id.text_view_item_name);
        TextView textViewItemDescription = (TextView)
            convertView.findViewById(R.id.text_view_item_description);

        //sets the text for item name and item description from the current item object
        textViewItemName.setText(currentItem.getItemName());
        textViewItemDescription.setText(currentItem.getItemDescription());

        // returns the view for the current row
        return convertView;
    }
}
</code>```

To optimize the listview's performance, a new row layout should be
  inflated only when convertView == null. This is because the adapter's
  getView method is called whenever the listview needs to show a new row
  on the screen. The convertView gets recycled in this process. Hence,
  the row layout should be inflated just once when convertView == null,
  and it contents should be updated on subsequent getView calls, instead
  of inflating a new row on each call which is very expensive.

I would also like to suggest using RecyclerView insted of ListView. RecyclerView was created to solve many problems that ListView had/has..

ContentLicense: CC BY-SA 4.0

Body:
I want to set two activities with one listview on each. To do it i've designed my own xml file for it's design, and so the listview has different textviews and images. But i'd like to use the same adapter on both listviews.

That's my java file of the carnes activity.

public class Carnes extends AppCompatActivity {
    private ListView lvItems;
    private Adapter adaptador;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_carnes);

        lvItems = (ListView) findViewById(R.id.lv_carnes);
        adaptador = (Adapter) new Adaptador(this, GetArrayItems());
        lvItems.setAdapter((ListAdapter) adaptador);
    }

    private ArrayList<Entidad> GetArrayItems() {
        ArrayList<Entidad> listItems = new ArrayList<>();
        listItems.add(new Entidad(R.drawable.calabacines_3, "Lomo", " 5 min.", 5, R.drawable.color_carnes));
        listItems.add(new Entidad(R.drawable.patatas_deluxe_especiadas_70523_300_150, "Pollo", " 20 min.", 4, R.drawable.color_carnes));
        listItems.add(new Entidad(R.drawable.tomate, "Pavo", " 1 min.", 3, R.drawable.color_carnes));

        return listItems;
    }
}

Here it is my Adapter:

public class Adaptador extends BaseAdapter {
    private Context context;
    private ArrayList<Entidad> listItems;

    public Adaptador(Context context, ArrayList<Entidad> listItems) {
        this.context = context;
        this.listItems = listItems;
    }

    @Override
    public int getCount() {
        return listItems.size();
    }

    @Override
    public Object getItem(int position) {
        return listItems.get(position);
    }

    @Override
    public long getItemId(int position) {
        return 0;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        Entidad Item = (Entidad) getItem(position);

        convertView = LayoutInflater.from(context).inflate(R.layout.elemento_lista, null);
        ImageView imgFoto = (ImageView) convertView.findViewById(R.id.imgFoto);
        TextView tvTitulo = (TextView) convertView.findViewById(R.id.tvTitulo);
        TextView tvTiempo = (TextView) convertView.findViewById(R.id.tvTiempo);
        RatingBar calificacion = (RatingBar) convertView.findViewById(R.id.ratingBarVerd);
        ImageView colorfondo = (ImageView) convertView.findViewById(R.id.colorfondo);

        imgFoto.setImageResource(Item.getImgFoto());
        tvTitulo.setText(Item.getTitulo());
        tvTiempo.setText(Item.getTiempo());
        calificacion.setRating(Item.getRating());
        colorfondo.setImageResource(Item.getColorfondo());

        return convertView;
    }
}

And i leave you the other activity which uses the same Adapter below (remember it's a different listview):

public class Verduras extends AppCompatActivity {
    private ListView lvItems;
    private Adapter adaptador;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_verduras);

        lvItems = (ListView) findViewById(R.id.lv_verduras);
        adaptador = (Adapter) new Adaptador(this, GetArrayItems());
        lvItems.setAdapter((ListAdapter) adaptador);
    }

    private ArrayList<Entidad> GetArrayItems() {
        ArrayList<Entidad> listItems = new ArrayList<>();
        listItems.add(new Entidad(R.drawable.calabacines_3, "Calabacines", " 10 min.", 4, R.drawable.color_verduras));
        listItems.add(new Entidad(R.drawable.patatas_deluxe_especiadas_70523_300_150, "Patatas", " 15 min.", 2, R.drawable.color_verduras));
        listItems.add(new Entidad(R.drawable.tomate, "Tomates", " 2 min.", 5, R.drawable.color_verduras));

        return listItems;
    }
}

And that's what i've used to define the variables:

public class Entidad {

    private int imgFoto;
    private String titulo;
    private String tiempo;
    private int ratingBar;
    private int colorfondo;

    public Entidad(int imgFoto, String titulo, String tiempo, int ratingBar, int colorfondo) {

        this.imgFoto = imgFoto;
        this.titulo = titulo;
        this.tiempo = tiempo;
        this.ratingBar = ratingBar;
        this.colorfondo = colorfondo;
    }

    public int getImgFoto() {
        return imgFoto;
    }

    public String getTitulo() {
        return titulo;
    }

    public String getTiempo() {
        return tiempo;
    }

    public int getRating() { return ratingBar; }

    public int getColorfondo() {
        return colorfondo;
    }
}

What it happens is that the code looks like it's OK, but when you run the app, then it suddenly stops without telling you what happende.

Thanks for helping and if you need anything else just tell me.

That's what appears onthe logcat.

05-29 16:08:38.173 2247-2247/com.test.platos4 E/AndroidRuntime: FATAL EXCEPTION: main
    android.content.res.Resources$NotFoundException: Resource ID #0x7f060059
        at android.content.res.Resources.getValue(Resources.java:1013)
        at android.support.v7.widget.ResourcesWrapper.getValue(ResourcesWrapper.java:209)
        at android.support.v7.widget.AppCompatDrawableManager.loadDrawableFromDelegates(AppCompatDrawableManager.java:331)
        at android.support.v7.widget.AppCompatDrawableManager.getDrawable(AppCompatDrawableManager.java:198)
        at android.support.v7.widget.AppCompatDrawableManager.getDrawable(AppCompatDrawableManager.java:191)
        at android.support.v7.content.res.AppCompatResources.getDrawable(AppCompatResources.java:102)
        at android.support.v7.widget.AppCompatImageHelper.setImageResource(AppCompatImageHelper.java:86)
        at android.support.v7.widget.AppCompatImageView.setImageResource(AppCompatImageView.java:94)
        at com.test.platos4.Adaptador.getView(Adaptador.java:62)
        at android.widget.AbsListView.obtainView(AbsListView.java:2271)
        at android.widget.ListView.makeAndAddView(ListView.java:1769)
        at android.widget.ListView.fillDown(ListView.java:672)
        at android.widget.ListView.fillFromTop(ListView.java:733)
        at android.widget.ListView.layoutChildren(ListView.java:1622)
        at android.widget.AbsListView.onLayout(AbsListView.java:2106)
        at android.view.View.layout(View.java:13754)
        at android.view.ViewGroup.layout(ViewGroup.java:4364)
        at android.widget.RelativeLayout.onLayout(RelativeLayout.java:948)
        at android.view.View.layout(View.java:13754)
        at android.view.ViewGroup.layout(ViewGroup.java:4364)
        at android.widget.FrameLayout.onLayout(FrameLayout.java:448)
        at android.view.View.layout(View.java:13754)
        at android.view.ViewGroup.layout(ViewGroup.java:4364)
        at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1649)
        at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1507)
        at android.widget.LinearLayout.onLayout(LinearLayout.java:1420)
        at android.view.View.layout(View.java:13754)
        at android.view.ViewGroup.layout(ViewGroup.java:4364)
        at android.widget.FrameLayout.onLayout(FrameLayout.java:448)
        at android.view.View.layout(View.java:13754)
        at android.view.ViewGroup.layout(ViewGroup.java:4364)
        at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1649)
        at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1507)
        at android.widget.LinearLayout.onLayout(LinearLayout.java:1420)
        at android.view.View.layout(View.java:13754)
        at android.view.ViewGroup.layout(ViewGroup.java:4364)
        at android.widget.FrameLayout.onLayout(FrameLayout.java:448)
        at android.view.View.layout(View.java:13754)
        at android.view.ViewGroup.layout(ViewGroup.java:4364)
        at android.view.ViewRootImpl.performLayout(ViewRootImpl.java:1868)
        at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:1689)
        at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1000)
        at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:4214)
        at android.view.Choreographer$CallbackRecord.run(Choreographer.java:725)
        at android.view.Choreographer.doCallbacks(Choreographer.java:555)
        at android.view.Choreographer.doFrame(Choreographer.java:525)
        at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:711)
        at android.os.Handler.handleCallback(Handler.java:615)
        at android.os.Handler.dispatchMessage(Handler.java:92)
        at android.os.Looper.loop(Looper.java:137)
        at android.app.ActivityThread.main(ActivityThread.java:4745)
        at java.lang.reflect.Method.invokeNative(Native Method)
        at java.lang.reflect.Method.invoke(Method.java:511)
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:786)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553)
        at dalvik.system.NativeStart.main(Native Method)
05-29 16:08:38.183 1379-1571/system_process W/ActivityManager:   Force finishing activity com.test.platos4/.Carnes
05-29 16:08:38.323 1379-1571/system_process D/dalvikvm: GC_FOR_ALLOC freed 658K, 12% free 22447K/25415K, paused 19ms, total 19ms
05-29 16:08:38.323 1379-1571/system_process W/ActivityManager:   Force finishing activity com.test.platos4/.Dishes
05-29 16:08:38.413 1121-1621/? D/gralloc_ranchu: gralloc_alloc: Creating ashmem region of size 1114112
05-29 16:08:38.853 1379-1392/system_process W/ActivityManager: Activity pause timeout for ActivityRecord{a78e7c78 com.test.platos4/.Carnes}
05-29 16:08:39.403 1121-1456/? D/gralloc_ranchu: gralloc_alloc: Creating ashmem region of size 1114112
05-29 16:08:39.663 1121-1456/? D/gralloc_ranchu: gralloc_alloc: Creating ashmem region of size 1114112
05-29 16:08:48.043 1379-1392/system_process W/ActivityManager: Launch timeout has expired, giving up wake lock!
    Activity idle timeout for ActivityRecord{a78e7c78 com.test.platos4/.Carnes}
05-29 16:08:48.863 1379-1392/system_process W/ActivityManager: Activity idle timeout for ActivityRecord{a7ce95d0 com.test.platos4/.Menu}
05-29 16:08:58.043 1379-1392/system_process W/ActivityManager: Activity destroy timeout for ActivityRecord{a7ce7888 com.test.platos4/.Dishes}
    Activity destroy timeout for ActivityRecord{a78e7c78 com.test.platos4/.Carnes}
05-29 16:09:00.013 1440-1440/com.android.systemui D/EGL_emulation: eglMakeCurrent: 0xb8af20d0: ver 2 0

Body:
In your code your not using the same adapter, you are instantiating a new adapter in both your Activities like: new Adaptador(...)

Here´s a tutorial on Using a BaseAdapter with ListView,

Here´s a snipe from the tutorial showing how getView() should work:

@Override
    public View getView(int position, View convertView, ViewGroup parent) {
        // inflate the layout for each list row
        if (convertView == null) {
            convertView = LayoutInflater.from(context).
                inflate(R.layout.layout_list_view_row_items, parent, false);
        }

        // get current item to be displayed
        Item currentItem = (Item) getItem(position);

        // get the TextView for item name and item description
        TextView textViewItemName = (TextView)
            convertView.findViewById(R.id.text_view_item_name);
        TextView textViewItemDescription = (TextView)
            convertView.findViewById(R.id.text_view_item_description);

        //sets the text for item name and item description from the current item object
        textViewItemName.setText(currentItem.getItemName());
        textViewItemDescription.setText(currentItem.getItemDescription());

        // returns the view for the current row
        return convertView;
    }
}

To optimize the listview's performance, a new row layout should be
  inflated only when convertView == null. This is because the adapter's
  getView method is called whenever the listview needs to show a new row
  on the screen. The convertView gets recycled in this process. Hence,
  the row layout should be inflated just once when convertView == null,
  and it contents should be updated on subsequent getView calls, instead
  of inflating a new row on each call which is very expensive.

I would also like to suggest using RecyclerView insted of ListView. RecyclerView was created to solve many problems that ListView had/has..


问:
I have problem linking my css to html using external method of writing css
Have been trying to link my html and my css writing code using css external method, can anybody put me through please?</p>

答:
Make sure your HTML and CSS file are in the same forder then use this:</p>

```<code><link rel="stylesheet" href="my CSS file name.CSS" type="text/CSS">
</code>```

Body:
Make sure your HTML and CSS file are in the same forder then use this:

<link rel="stylesheet" href="my CSS file name.CSS" type="text/CSS">


问:
I need a substring from JsonPath
The given string is:

```<code>{"POWER":"ON","Dimmer":2,"Color":"12345678","HSBColor":"120,100,2","Channel":[0,1,0,0]}
</code>```

result should be:
123456

In the Android app MQTT Dash I need only the first six characters from the color.

With $.Color I get:

Invalid color format

答:
I did the following for a sonoff/trasmota color bulb:

1) Leave blank the field "Extract from JSON Path"

2) on the event "On Receive", write the following code:

```<code>event.payload = JSON.parse(event.payload)['Color'].substring(0,6);
</code>```

Hope this helps.

Cheers.

Title: I need a substring from JsonPath

Body:
The given string is:

{"POWER":"ON","Dimmer":2,"Color":"12345678","HSBColor":"120,100,2","Channel":[0,1,0,0]}

result should be:
123456

In the Android app MQTT Dash I need only the first six characters from the color.

With $.Color I get:

Invalid color format

Body:
I did the following for a sonoff/trasmota color bulb:

1) Leave blank the field "Extract from JSON Path"

2) on the event "On Receive", write the following code:

event.payload = JSON.parse(event.payload)['Color'].substring(0,6);

Hope this helps.

Cheers.


问:
How to block the click event to the background of DialogFragment around Samsung S9 Edge button
I have a UI requirement showing a blocking DialogFragment, which can not be dismissed by clicking on the background.
Also when the DialogFragment is showing, any view under it cannot be clicked.

Things are working well except on the Samsung S9 device.

On Samsung S9, which has an edge button, when clicking around the edge button's edge, the view under the DialogFragment got clicked and the event performed, which is not as expected.

Here is a sample code:

```<code>public class MainActivity extends AppCompatActivity {

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    findViewById(R.id.button).setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            MyDialogFragment myDialogFragment = new MyDialogFragment();
            myDialogFragment.show(getSupportFragmentManager(), MyDialogFragment.TAG);

        }
    });

    findViewById(R.id.background).setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            Log.e("wrong", "clicked!!!!---------------");
            Toast.makeText(MainActivity.this, "Click!", Toast.LENGTH_LONG).show();
        }
    });
}
</code>```

}

The layout is quite simple, just a LinearLayout with a button inside it.
Clicking button will show the blocking dialog.
The LinearLayout id is background, which should not be clicked after the dialog has shown.

The dialog code:

public class MyDialogFragment extends DialogFragment {
    public static final String TAG = "Dialog";

```<code>@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setCancelable(false);
}

@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container,
                         @Nullable Bundle savedInstanceState) {
    View view = inflater.inflate(R.layout.my_dialog_layout, container, false);
    getDialog().setCanceledOnTouchOutside(false);
    return view;
}

@Override
public void onResume() {
    Window window = getDialog().getWindow();
    Point size = new Point();
    Display display = window.getWindowManager().getDefaultDisplay();
    display.getSize(size);
    window.setLayout((int) (size.x * 0.8), WindowManager.LayoutParams.WRAP_CONTENT);
    window.setGravity(Gravity.CENTER);
    super.onResume();
}
</code>```

}

But now when the dialog is showing, click the area on the edge button, the background click listener can be entered, I can get the log and toast.

How to prevent this?

答:
In the event that is firing I'd do</p>

```<code>Fragment currentFrag = getSupportFragmentManager().findFragmentByTag(MyDialogFragment_TAG);
if (!(currentFrag instanceof MyDialogFragment))
{
  // your code for when you're dialog fragment is not visible
}
</code>```

Body:
I have a UI requirement showing a blocking DialogFragment, which can not be dismissed by clicking on the background.
Also when the DialogFragment is showing, any view under it cannot be clicked.

Things are working well except on the Samsung S9 device.

On Samsung S9, which has an edge button, when clicking around the edge button's edge, the view under the DialogFragment got clicked and the event performed, which is not as expected.

Here is a sample code:

public class MainActivity extends AppCompatActivity {

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    findViewById(R.id.button).setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            MyDialogFragment myDialogFragment = new MyDialogFragment();
            myDialogFragment.show(getSupportFragmentManager(), MyDialogFragment.TAG);

        }
    });

    findViewById(R.id.background).setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            Log.e("wrong", "clicked!!!!---------------");
            Toast.makeText(MainActivity.this, "Click!", Toast.LENGTH_LONG).show();
        }
    });
}

}

The layout is quite simple, just a LinearLayout with a button inside it.
Clicking button will show the blocking dialog.
The LinearLayout id is background, which should not be clicked after the dialog has shown.

The dialog code:

public class MyDialogFragment extends DialogFragment {
    public static final String TAG = "Dialog";

@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setCancelable(false);
}

@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container,
                         @Nullable Bundle savedInstanceState) {
    View view = inflater.inflate(R.layout.my_dialog_layout, container, false);
    getDialog().setCanceledOnTouchOutside(false);
    return view;
}

@Override
public void onResume() {
    Window window = getDialog().getWindow();
    Point size = new Point();
    Display display = window.getWindowManager().getDefaultDisplay();
    display.getSize(size);
    window.setLayout((int) (size.x * 0.8), WindowManager.LayoutParams.WRAP_CONTENT);
    window.setGravity(Gravity.CENTER);
    super.onResume();
}

}

But now when the dialog is showing, click the area on the edge button, the background click listener can be entered, I can get the log and toast.

How to prevent this?

Body:
In the event that is firing I'd do

Fragment currentFrag = getSupportFragmentManager().findFragmentByTag(MyDialogFragment_TAG);
if (!(currentFrag instanceof MyDialogFragment))
{
  // your code for when you're dialog fragment is not visible
}


问:
Shortest path between raw geo coordinates and a node of a graph
I have implemented a simple Dijkstra's algorithm for finding the shortest path on an .osm map with Java.

The pathfinding in a graph which is created from an .osm file works pretty well. But in case the user's current location and/or destination is not a node of this graph (just raw coordinates) how do we 'link' those coordinates to the graph to make pathfinding work?

The simple straightforward solution "find the nearest to the current location node and draw a straight line" doesn't seem to be realistic. What if we have a situation like on the attached picture? (UPD)

The problem here is that before we start any 'smart' pathfinding algorithms (like Dijkstra's) we 'link' the current position to the graph, but it is just dumb formula (a hypotenuse from Pythagorean theorem)  of finding the nearest node in terms of geographical coordinates and this formula is not 'pathinding' - it can not take obstacles and types of nodes into account.

To paraphrase it - how do we find the shortest path between A and B if B is a node in a graph, and A is not a node?

Have you heard of any other solutions to this problem?

答:
The process you're describing is "map matching," and it uses a spatial index to find the nearest node.

One common approach is to construct a quadtree that contains all your nodes, then identify the quad that contains your point, then calculate the distance from your point to all nodes in the quad (recognizing that longitudinal degrees are shorter than latitudinal degrees). If there are no nodes in the quad then you progressively expand your search. There are several caveats with quadtrees, but this should at least get you started.

ContentLicense: CC BY-SA 3.0


问:
Adding strings in lists together
I want to transform the list ["A","B","A","A","B"] to the list ["AB","BA","AA","AB"].

I have tried to define a new list in which the first element is deleted and then add the strings of the lists together. After which I plan to delete the last element of the new list to get the result.

```<code>lista = sequences
lista.pop(0)
print(lista)

for x in range(sequences):
    mc =sequences[x]+lista[x]
</code>```

But all I get is

TypeError: 'list' object cannot be interpreted as an integer

Any help is welcome.

Edit : Thank you guys, all your solutions worked perfectly :)

答:
There are several issues in your original code:

```<code>sequences = ["A","B","A","A","B"]
lista = sequences
lista.pop(0)
print(lista)

for x in range(sequences):
    mc =sequences[x]+lista[x]
</code>```

Firstly, the statement lista = sequences does not make a copy of sequences. Instead, lista and sequences become two different names for the same list. What you do using one name also happens to the other. lista.pop(0) is the same as sequences.pop(0). If you want a copy, then import the copy library.

```<code>import copy

sequences = ["A","B","A","A","B"]
lista = copy.copy(sequences)
lista.pop(0)
print(lista)

for x in range(sequences):
    mc =sequences[x]+lista[x]
</code>```

Secondly, your statement range(sequences) is incorrect. The range() function accepts integers as input, not lists. That's what gave you TypeError: 'list' object cannot be interpreted as an integer

```<code># VALID
range(5)
range(3)
range(10)

# INVALID
range(["A","B","A"])
range(["eyes", "nose", "tail"])
</code>```

sequences is a list. You want range(len(sequences)) notrange(sequences)

In the end, we can modify your original code to work:

```<code>import copy

sequences = ["A","B","A","A","B"]
lista = copy.copy(sequences)
lista.pop(0)
print(lista) # prints ["B","A","A","B"]

mc = list()
for x in range(len(lista)):
    mc.append(lista[x] + sequences[x + 1])
</code>```

Title: Adding strings in lists together

Body:
I want to transform the list ["A","B","A","A","B"] to the list ["AB","BA","AA","AB"].

I have tried to define a new list in which the first element is deleted and then add the strings of the lists together. After which I plan to delete the last element of the new list to get the result.

lista = sequences
lista.pop(0)
print(lista)

for x in range(sequences):
    mc =sequences[x]+lista[x]

But all I get is

TypeError: 'list' object cannot be interpreted as an integer

Any help is welcome.

Edit : Thank you guys, all your solutions worked perfectly :)

Body:
There are several issues in your original code:

sequences = ["A","B","A","A","B"]
lista = sequences
lista.pop(0)
print(lista)

for x in range(sequences):
    mc =sequences[x]+lista[x]

Firstly, the statement lista = sequences does not make a copy of sequences. Instead, lista and sequences become two different names for the same list. What you do using one name also happens to the other. lista.pop(0) is the same as sequences.pop(0). If you want a copy, then import the copy library.

import copy

sequences = ["A","B","A","A","B"]
lista = copy.copy(sequences)
lista.pop(0)
print(lista)

for x in range(sequences):
    mc =sequences[x]+lista[x]

Secondly, your statement range(sequences) is incorrect. The range() function accepts integers as input, not lists. That's what gave you TypeError: 'list' object cannot be interpreted as an integer

# VALID
range(5)
range(3)
range(10)

# INVALID
range(["A","B","A"])
range(["eyes", "nose", "tail"])

sequences is a list. You want range(len(sequences)) notrange(sequences)

In the end, we can modify your original code to work:

import copy

sequences = ["A","B","A","A","B"]
lista = copy.copy(sequences)
lista.pop(0)
print(lista) # prints ["B","A","A","B"]

mc = list()
for x in range(len(lista)):
    mc.append(lista[x] + sequences[x + 1])


问:
How to plot graphs iteratively on Jupyter Notebook
I'm working with incremental graphs, so I would like to plot the current graph every time I insert a new edge on top of the previous drawing.

With this code I can generate one figure at a time, but they only show up after the iteration has ended.

```<code>import random
import time
import networkx as nx
import matplotlib
import matplotlib.pyplot as plt
import numpy as np
%matplotlib notebook

#Generating some random edges
M = 10
N = 4
edges = []
for i in range(M):
    s = random.randrange(N) + 1
    t = random.randrange(N) + 1
    edges.append((s,t))

G = nx.DiGraph()
G.add_nodes_from(range(1, 5))

plt.subplot(121)
plt.ion()

nx.draw(G, with_labels=True, font_weight='bold')

for edge in edges:
    plt.figure()
    G.add_edge(*edge)
    nx.draw(G, with_labels=True, font_weight='bold')
    time.sleep(1)
</code>```

But what I really want is to see the graph being redrawn on every iteration, or at least being able to stack them using Matplotlib's interactive mode so I can go forward and backward.

I've been searching for days and have found some examples working with graphs like bar chart, pie chart and such, but the graph I mean is the data structure, not charts.

答:
Here is a suggestion using FuncAnimation, which greatly simplifies the whole process of creating animated/live graphs in matplotlib

```<code>import random
import time
import networkx as nx
import matplotlib
import matplotlib.pyplot as plt
import numpy as np
%matplotlib notebook

#Generating some random edges
M = 10
N = 4
edges = []
for i in range(M):
    s = random.randrange(N) + 1
    t = random.randrange(N) + 1
    edges.append((s,t))

G = nx.DiGraph()
G.add_nodes_from(range(1, 5))

fig = plt.figure()
ax = plt.subplot(121)

def init():
    nx.draw(G, with_labels=True, font_weight='bold')

def update(edge):
    G.add_edge(*edge)
    nx.draw(G, with_labels=True, font_weight='bold')

ani = animation.FuncAnimation(fig, update, frames=edges, interval=1000., init_func=init, repeat=False)
</code>```

Body:
I'm working with incremental graphs, so I would like to plot the current graph every time I insert a new edge on top of the previous drawing.

With this code I can generate one figure at a time, but they only show up after the iteration has ended.

import random
import time
import networkx as nx
import matplotlib
import matplotlib.pyplot as plt
import numpy as np
%matplotlib notebook

#Generating some random edges
M = 10
N = 4
edges = []
for i in range(M):
    s = random.randrange(N) + 1
    t = random.randrange(N) + 1
    edges.append((s,t))

G = nx.DiGraph()
G.add_nodes_from(range(1, 5))

plt.subplot(121)
plt.ion()

nx.draw(G, with_labels=True, font_weight='bold')

for edge in edges:
    plt.figure()
    G.add_edge(*edge)
    nx.draw(G, with_labels=True, font_weight='bold')
    time.sleep(1)

But what I really want is to see the graph being redrawn on every iteration, or at least being able to stack them using Matplotlib's interactive mode so I can go forward and backward.

I've been searching for days and have found some examples working with graphs like bar chart, pie chart and such, but the graph I mean is the data structure, not charts.

Body:
Here is a suggestion using FuncAnimation, which greatly simplifies the whole process of creating animated/live graphs in matplotlib

import random
import time
import networkx as nx
import matplotlib
import matplotlib.pyplot as plt
import numpy as np
%matplotlib notebook

#Generating some random edges
M = 10
N = 4
edges = []
for i in range(M):
    s = random.randrange(N) + 1
    t = random.randrange(N) + 1
    edges.append((s,t))

G = nx.DiGraph()
G.add_nodes_from(range(1, 5))

fig = plt.figure()
ax = plt.subplot(121)

def init():
    nx.draw(G, with_labels=True, font_weight='bold')

def update(edge):
    G.add_edge(*edge)
    nx.draw(G, with_labels=True, font_weight='bold')

ani = animation.FuncAnimation(fig, update, frames=edges, interval=1000., init_func=init, repeat=False)


问:
Sqlite: multiple update (find and replace) case insensitive
I use DB Browser for SQLite to visualize and update an sqlite file.

I am able to do run a case sensitive query to update some text like this:

```<code>UPDATE itemNotes  SET note = REPLACE(note ,  'sometext', 'abc');
</code>```

But I would like to match replace all case combinations of sometext (e.g. sometext, SOMEtext, SOmeText...)

I tried to do this :

```<code>UPDATE itemNotes  SET note = REPLACE(LOWER(note),  'sometext', 'abc');
</code>```

But this transform the whole content of the field note in lower case which isn't what I want.

I also tried these query but without success:

```<code>UPDATE itemNotes  SET note = REPLACE(note, BINARY 'sometext', 'abc')
UPDATE itemNotes  SET note = REPLACE(note, COLLATE Latin1_General_CS_AS'sometext', 'abc')
</code>```

I am doing it on the zotero.sqlite, which is created by this file   (line 85).
The table is created by this query

```<code>CREATE TABLE itemNotes (
    itemID INTEGER PRIMARY KEY,
    parentItemID INT,
    note TEXT,
    title TEXT,
    FOREIGN KEY (itemID) REFERENCES items(itemID) ON DELETE CASCADE,
    FOREIGN KEY (parentItemID) REFERENCES items(itemID) ON DELETE CASCADE
);
</code>```

答:
Nosyara answer works great but it only removes 1 instance at a time.

I also tried this from here:

```<code>UPDATE itemNotes
SET
  note = SUBSTR(note, 0, INSTR(LOWER(note), 'sometext')) || 'abc' || SUBSTR(note, INSTR(LOWER(note), 'sometext')+sometext_len)
WHERE
  note LIKE "%sometext%";
</code>```

But when I have many occurence of sometext in a field note, then only the first on is removed. Based on a comment on this question, I ended up using python to replace the sqlite, see here

Body:
I use DB Browser for SQLite to visualize and update an sqlite file.

I am able to do run a case sensitive query to update some text like this:

UPDATE itemNotes  SET note = REPLACE(note ,  'sometext', 'abc');

But I would like to match replace all case combinations of sometext (e.g. sometext, SOMEtext, SOmeText...)

I tried to do this :

UPDATE itemNotes  SET note = REPLACE(LOWER(note),  'sometext', 'abc');

But this transform the whole content of the field note in lower case which isn't what I want.

I also tried these query but without success:

UPDATE itemNotes  SET note = REPLACE(note, BINARY 'sometext', 'abc')
UPDATE itemNotes  SET note = REPLACE(note, COLLATE Latin1_General_CS_AS'sometext', 'abc')

I am doing it on the zotero.sqlite, which is created by this file   (line 85).
The table is created by this query

CREATE TABLE itemNotes (
    itemID INTEGER PRIMARY KEY,
    parentItemID INT,
    note TEXT,
    title TEXT,
    FOREIGN KEY (itemID) REFERENCES items(itemID) ON DELETE CASCADE,
    FOREIGN KEY (parentItemID) REFERENCES items(itemID) ON DELETE CASCADE
);

Body:
Nosyara answer works great but it only removes 1 instance at a time.

I also tried this from here:

UPDATE itemNotes
SET
  note = SUBSTR(note, 0, INSTR(LOWER(note), 'sometext')) || 'abc' || SUBSTR(note, INSTR(LOWER(note), 'sometext')+sometext_len)
WHERE
  note LIKE "%sometext%";

But when I have many occurence of sometext in a field note, then only the first on is removed. Based on a comment on this question, I ended up using python to replace the sqlite, see here


问:
How to prevent the user from repetitively inputting same number
I am creating a program in java where the user has to guess a random number generated by the computer, The user gets 20 tries in total to guess the number,if the user enters the same number repeatedly it should show an error message and no count as one of their guesses but am unsure how to do this. For example if the users first guess is 5 and they guess 5 again an error message should appear saying "You have already entered this number </p>

```<code>package guessinggame2;
import java.util.Scanner;

public class GuessingGame2 {

  static Scanner kboard = new Scanner(System.in);

  public static void main(String args[]) // start of main
  {
    System.out.println("Welcome to the guessing game, the computer will
    generate a random number that you have to guess, good luck!");

    int secret_number = 0;
    int number_of_guesses = 0;
    Scanner input = new Scanner(System.in);
    int user_guess;
    int used_number = 0;

    secret_number = (int)(Math.random()*100) + 1;
    System.out.println("The computer has generated it's number");

    for(int i=0; i<20;i++) {

      System.out.println("Please make your guess");
      user_guess = kboard.nextInt();
      number_of_guesses++;

      if (user_guess == secret_number)
      {
        System.out.println("Your guess is correct it took you " +
        number_of_guesses + " guesses");
      }

      else if  (user_guess < secret_number)
      {
        System.out.println("Your guess is too low try again");
      }

      else if (user_guess > secret_number)
      {
        System.out.println("Your guess is too high try again");
      }

      System.out.println (20 - number_of_guesses + " Guesses remaining");
    }
  }
}
</code>```

答:
Create an array using ArrayList and give it a name (ex. 'entered_numbers')

```<code>ArrayList<Integer> entered_numbers = new ArrayList<Integer>();
</code>```

2. Every time the user inputs a number, check using contains() whether or not the number is in the ArrayList.

If it is, display your message (don't number_of_guesses++)

If it isn't, add it using add() and continue your own checks.

```<code>if(entered_numbers.contains(user_guess)) {
    System.out.println("You have already entered this number");
    continue;
} else {
    entered_numbers.add(user_guess);
    // Check if == secret number,
    // Check if < secret number,
    // Check if > secret number
}
</code>```

Others have suggested using HashSets which is better for performance.

Complexity using ArrayList is O(n) while HashSet is O(1).

I opted for an easier approach using ArrayList, and it doesn't affect performance too much because you're not going to store a lot of data inside that ArrayList.

See more about complexity here: https://www.baeldung.com/java-collections-complexity

Body:
I am creating a program in java where the user has to guess a random number generated by the computer, The user gets 20 tries in total to guess the number,if the user enters the same number repeatedly it should show an error message and no count as one of their guesses but am unsure how to do this. For example if the users first guess is 5 and they guess 5 again an error message should appear saying "You have already entered this number

package guessinggame2;
import java.util.Scanner;

public class GuessingGame2 {

  static Scanner kboard = new Scanner(System.in);

  public static void main(String args[]) // start of main
  {
    System.out.println("Welcome to the guessing game, the computer will
    generate a random number that you have to guess, good luck!");

    int secret_number = 0;
    int number_of_guesses = 0;
    Scanner input = new Scanner(System.in);
    int user_guess;
    int used_number = 0;

    secret_number = (int)(Math.random()*100) + 1;
    System.out.println("The computer has generated it's number");

    for(int i=0; i<20;i++) {

      System.out.println("Please make your guess");
      user_guess = kboard.nextInt();
      number_of_guesses++;

      if (user_guess == secret_number)
      {
        System.out.println("Your guess is correct it took you " +
        number_of_guesses + " guesses");
      }

      else if  (user_guess < secret_number)
      {
        System.out.println("Your guess is too low try again");
      }

      else if (user_guess > secret_number)
      {
        System.out.println("Your guess is too high try again");
      }

      System.out.println (20 - number_of_guesses + " Guesses remaining");
    }
  }
}

Body:
Create an array using ArrayList and give it a name (ex. 'entered_numbers')

ArrayList<Integer> entered_numbers = new ArrayList<Integer>();

2. Every time the user inputs a number, check using contains() whether or not the number is in the ArrayList.

If it is, display your message (don't number_of_guesses++)

If it isn't, add it using add() and continue your own checks.

if(entered_numbers.contains(user_guess)) {
    System.out.println("You have already entered this number");
    continue;
} else {
    entered_numbers.add(user_guess);
    // Check if == secret number,
    // Check if < secret number,
    // Check if > secret number
}

Others have suggested using HashSets which is better for performance.

Complexity using ArrayList is O(n) while HashSet is O(1).

I opted for an easier approach using ArrayList, and it doesn't affect performance too much because you're not going to store a lot of data inside that ArrayList.

See more about complexity here: https://www.baeldung.com/java-collections-complexity


问:
MongoDb.Linq equivalent query for conditional aggregator
I'm grouping my data with MongoDb.Linq in the following way:

```<code>group r1 by new { r1.SupId, r1.SupFullName } into g2
select new
{
    g2.Key.SupFullName,
    Volunteers = from v0 in g2
                 where v0.VolId != g2.Key.SupId
                 select new { v0.VolFullName, v0.VolPeopleCount }
}
</code>```

That is, I want only in Volunteers those which Ids are not the same as the group's key. I was expecting the driver to generate a conditional $push, but instead it gives a plain one:

```<code>"$push" : {
    "VolFullName" : "$VolFullName",
    "VolPeopleCount" : "$VolPeopleCount"
}
</code>```

Now, by reading this post I was able to transform the above query into the following one:

```<code>"$push": {
    "$cond": [
        { "$ne": [ "$VolId", "$SupId" ] },
        {
            "VolFullName": "$VolFullName",
            "VolPeopleCount": "$VolPeopleCount"
        },
        null
     ]
 }
</code>```

Which gives me the desired results. I'd like to know how, if it's possible, to instruct the csharp driver to generate a query like the above. Thanks in advance!

EDIT: Following @mickl suggestion I was able to generate a conditional $push (and also a conditional $sum) but the result was not as expected. Suppose I have the following docs in my collection:

```<code>{ N: "P_1", S: { I: "S_1", FN: "S_1" }, C: { I: "S_1", FN: "S_1" } }
{ N: "P_2", S: { I: "S_1", FN: "S_1" }, C: { I: "S_1", FN: "S_1" } }
{ N: "P_3", S: { I: "S_1", FN: "S_1" }, C: { I: "S_1", FN: "S_1" } }
{ N: "P_4", S: { I: "S_1", FN: "S_1" }, C: { I: "C_2", FN: "C_2" } }
{ N: "P_5", S: { I: "S_1", FN: "S_1" }, C: { I: "C_2", FN: "C_2" } }
{ N: "P_6", S: { I: "S_1", FN: "S_1" }, C: { I: "C_2", FN: "C_2" } }
{ N: "P_7", S: { I: "S_1", FN: "S_1" }, C: { I: "C_3", FN: "C_3" } }
{ N: "P_8", S: { I: "S_1", FN: "S_1" }, C: { I: "C_3", FN: "C_3" } }
{ N: "P_9", S: { I: "S_1", FN: "S_1" }, C: { I: "C_3", FN: "C_3" } }
</code>```

Here N, I, FN, S and C means name, id, full name, supervisor and creator respectively. So as you can see supervisor S_1 is supervising every doc, has created 3 docs and there are 6 docs created by 2 other creators that are supervised as well by S_1. What I want to do is to summarize those docs by supervisors and then by creators with the amount of docs (people) created. So, my LINQ query looks like:

```<code>var q = from p in col.AsQueryable()
        group p by new
        {
           SupFullName = p.S.FN,
           SupId = p.S.I,
           CtorFullName = p.C.FN,
           CtorId = p.C.I
        } into g1
        select new
        {
            g1.Key.SupFullName,
            g1.Key.SupId,
            VolFullName = g1.Key.CtorFullName,
            VolId = g1.Key.CtorId,
            VolPeopleCount = g1.LongCount()
        } into r1
        group r1 by new { r1.SupId, r1.SupFullName } into g2
        select new
        {
           g2.Key.SupFullName,
           g2.Key.SupId,
           Volunteers = g2.Select(v => v.VolId != g2.Key.SupId
                           ? new { v.VolId, v.VolFullName, v.VolPeopleCount }
                           : null),
          SupPeopleCount = g2.Select(v => v.VolId == g2.Key.SupId
                               ? v.VolPeopleCount
                               : 0).Sum()
        } into r2
        orderby r2.SupPeopleCount descending
        select r2;
</code>```

The output that query give me is:

```<code>Supervisor: S_1, PeopleCount: 0
   Creator: C_3, PeopleCount: 3
   Creator: C_2, PeopleCount: 3
   Creator: S_1, PeopleCount: 3
</code>```

Which isn't what I want. Correct output would be

```<code>Supervisor: S_1, PeopleCount: 3
   Creator: C_3, PeopleCount: 3
   Creator: C_2, PeopleCount: 3
</code>```

It generates the conditional aggregators in the following way (If I remove the prefix $_id in the condition and leave just $SupId it works like a charm):

```<code>"__agg0": {
      "$push": {
         "$cond": [
             { "$ne": [ "$VolId", "$_id.SupId" ] },
             {
                "VolId": "$VolId",
                "VolFullName": "$VolFullName",
                "VolPeopleCount": "$VolPeopleCount"
             },
             null
         ]
      }
},
"__agg1": {
    "$sum": {
       "$cond": [
           { "$eq": [ "$VolId", "$_id.SupId" ] },
           "$VolPeopleCount",
           NumberLong(0)
       ]
   }
}
</code>```

Thanks!

答:
You can run Select and use ternary operator in your LINQ statement:

```<code>group r1 by new { r1.SupId, r1.SupFullName } into g2
select new
{
    g2.Key.SupFullName,
    Volunteers = g2.Select(x => x.VolId != x.SupId ? new { x.VolFullName, x.VolPeopleCount }: null)
};
</code>```

This gets translated into following aggregation pipeline:

```<code>{
    "$group" : {
        "_id" : { "SupId" : "$SupId", "SupFullName" : "$SupFullName" },
        "__agg0" : {
            "$push" : {
                "$cond" : [
                        { "$ne" : ["$VolId", "$SupId"] },
                        { "VolFullName" : "$VolFullName", "VolPeopleCount" : "$VolPeopleCount" },
                        null
                    ]
                }
            }
        }
},
{ "$project" : { "SupFullName" : "$_id.SupFullName", "Volunteers" : "$__agg0", "_id" : 0 } }
</code>```

Body:
I'm grouping my data with MongoDb.Linq in the following way:

group r1 by new { r1.SupId, r1.SupFullName } into g2
select new
{
    g2.Key.SupFullName,
    Volunteers = from v0 in g2
                 where v0.VolId != g2.Key.SupId
                 select new { v0.VolFullName, v0.VolPeopleCount }
}

That is, I want only in Volunteers those which Ids are not the same as the group's key. I was expecting the driver to generate a conditional $push, but instead it gives a plain one:

"$push" : {
    "VolFullName" : "$VolFullName",
    "VolPeopleCount" : "$VolPeopleCount"
}

Now, by reading this post I was able to transform the above query into the following one:

"$push": {
    "$cond": [
        { "$ne": [ "$VolId", "$SupId" ] },
        {
            "VolFullName": "$VolFullName",
            "VolPeopleCount": "$VolPeopleCount"
        },
        null
     ]
 }

Which gives me the desired results. I'd like to know how, if it's possible, to instruct the csharp driver to generate a query like the above. Thanks in advance!

EDIT: Following @mickl suggestion I was able to generate a conditional $push (and also a conditional $sum) but the result was not as expected. Suppose I have the following docs in my collection:

{ N: "P_1", S: { I: "S_1", FN: "S_1" }, C: { I: "S_1", FN: "S_1" } }
{ N: "P_2", S: { I: "S_1", FN: "S_1" }, C: { I: "S_1", FN: "S_1" } }
{ N: "P_3", S: { I: "S_1", FN: "S_1" }, C: { I: "S_1", FN: "S_1" } }
{ N: "P_4", S: { I: "S_1", FN: "S_1" }, C: { I: "C_2", FN: "C_2" } }
{ N: "P_5", S: { I: "S_1", FN: "S_1" }, C: { I: "C_2", FN: "C_2" } }
{ N: "P_6", S: { I: "S_1", FN: "S_1" }, C: { I: "C_2", FN: "C_2" } }
{ N: "P_7", S: { I: "S_1", FN: "S_1" }, C: { I: "C_3", FN: "C_3" } }
{ N: "P_8", S: { I: "S_1", FN: "S_1" }, C: { I: "C_3", FN: "C_3" } }
{ N: "P_9", S: { I: "S_1", FN: "S_1" }, C: { I: "C_3", FN: "C_3" } }

Here N, I, FN, S and C means name, id, full name, supervisor and creator respectively. So as you can see supervisor S_1 is supervising every doc, has created 3 docs and there are 6 docs created by 2 other creators that are supervised as well by S_1. What I want to do is to summarize those docs by supervisors and then by creators with the amount of docs (people) created. So, my LINQ query looks like:

var q = from p in col.AsQueryable()
        group p by new
        {
           SupFullName = p.S.FN,
           SupId = p.S.I,
           CtorFullName = p.C.FN,
           CtorId = p.C.I
        } into g1
        select new
        {
            g1.Key.SupFullName,
            g1.Key.SupId,
            VolFullName = g1.Key.CtorFullName,
            VolId = g1.Key.CtorId,
            VolPeopleCount = g1.LongCount()
        } into r1
        group r1 by new { r1.SupId, r1.SupFullName } into g2
        select new
        {
           g2.Key.SupFullName,
           g2.Key.SupId,
           Volunteers = g2.Select(v => v.VolId != g2.Key.SupId
                           ? new { v.VolId, v.VolFullName, v.VolPeopleCount }
                           : null),
          SupPeopleCount = g2.Select(v => v.VolId == g2.Key.SupId
                               ? v.VolPeopleCount
                               : 0).Sum()
        } into r2
        orderby r2.SupPeopleCount descending
        select r2;

The output that query give me is:

Supervisor: S_1, PeopleCount: 0
   Creator: C_3, PeopleCount: 3
   Creator: C_2, PeopleCount: 3
   Creator: S_1, PeopleCount: 3

Which isn't what I want. Correct output would be

Supervisor: S_1, PeopleCount: 3
   Creator: C_3, PeopleCount: 3
   Creator: C_2, PeopleCount: 3

It generates the conditional aggregators in the following way (If I remove the prefix $_id in the condition and leave just $SupId it works like a charm):

"__agg0": {
      "$push": {
         "$cond": [
             { "$ne": [ "$VolId", "$_id.SupId" ] },
             {
                "VolId": "$VolId",
                "VolFullName": "$VolFullName",
                "VolPeopleCount": "$VolPeopleCount"
             },
             null
         ]
      }
},
"__agg1": {
    "$sum": {
       "$cond": [
           { "$eq": [ "$VolId", "$_id.SupId" ] },
           "$VolPeopleCount",
           NumberLong(0)
       ]
   }
}

Thanks!

Body:
You can run Select and use ternary operator in your LINQ statement:

group r1 by new { r1.SupId, r1.SupFullName } into g2
select new
{
    g2.Key.SupFullName,
    Volunteers = g2.Select(x => x.VolId != x.SupId ? new { x.VolFullName, x.VolPeopleCount }: null)
};

This gets translated into following aggregation pipeline:

{
    "$group" : {
        "_id" : { "SupId" : "$SupId", "SupFullName" : "$SupFullName" },
        "__agg0" : {
            "$push" : {
                "$cond" : [
                        { "$ne" : ["$VolId", "$SupId"] },
                        { "VolFullName" : "$VolFullName", "VolPeopleCount" : "$VolPeopleCount" },
                        null
                    ]
                }
            }
        }
},
{ "$project" : { "SupFullName" : "$_id.SupFullName", "Volunteers" : "$__agg0", "_id" : 0 } }


问:
Get list of time zones with time difference from GMT
I have a Django application and I have a list of timezones hardcoded. I know pytz can be used to get a list of all timezones. But it does not show their time difference with respect to GMT. Please suggest how to get a list like this.

```<code>TIMEZONE_CHOICES = (
    ("<DstTzInfo 'Africa/Abidjan' LMT-1 day, 23:44:00 STD>", "<DstTzInfo 'Africa/Abidjan' LMT-1 day, 23:44:00 STD>"),
    ("<DstTzInfo 'Africa/Accra' LMT-1 day, 23:59:00 STD>", "<DstTzInfo 'Africa/Accra' LMT-1 day, 23:59:00 STD>"),
    ("<DstTzInfo 'Africa/Addis_Ababa' LMT+2:27:00 STD>", "<DstTzInfo 'Africa/Addis_Ababa' LMT+2:27:00 STD>"),
    ("<DstTzInfo 'Africa/Algiers' LMT+0:12:00 STD>", "<DstTzInfo 'Africa/Algiers' LMT+0:12:00 STD>"),
    ("<DstTzInfo 'Africa/Asmara' LMT+2:27:00 STD>", "<DstTzInfo 'Africa/Asmara' LMT+2:27:00 STD>"),...)
</code>```

答:
Assuming the time difference from UTC is an acceptable alternative to GMT (UTC and GMT are nearly but not exactly the same), you can get time zone offset and related information from the pytz.timezone object.

For time zones with multiple offsets (due to daylight savings, historical changes, etc), you can get the related zones and offsets from the _tzinfos attribute. For time zones with a single offset, you can get the offset from the _utcoffset attribute.

Following example creates a dict where each time zone in pytz.all_timezones is a key and the value is a list of tuples containing the related zone and offset information.

```<code>from pytz import all_timezones, timezone

timezones = {}
for tz in all_timezones:
    tzinfos = getattr(timezone(tz), '_tzinfos', None)
    if tzinfos:
        timezones[tz] = [(zone, str(offset)) for offset, dst, zone in tzinfos]
    else:
        timezones[tz] = [(tz, str(timezone(tz)._utcoffset))]

print(timezones)
# {
#     'Africa/Abidjan': [('LMT', '-1 day, 23:44:00'), ('GMT', '0:00:00')],
#     'Africa/Accra': [('LMT', '-1 day, 23:59:00'), ('GMT', '0:00:00'), ('+0020', '0:20:00')],
#     'Africa/Addis_Ababa': [('LMT', '2:27:00'), ('EAT', '3:00:00'), ('+0230', '2:30:00'), ('+0245', '2:45:00')],
#     'Africa/Algiers': [('LMT', '0:12:00'), ('PMT', '0:09:00'), ('WET', '0:00:00'), ('WEST', '1:00:00'), ('CET', '1:00:00'), ('CEST', '2:00:00')],
#     'Africa/Asmara': [('LMT', '2:27:00'), ('EAT', '3:00:00'), ('+0230', '2:30:00'), ('+0245', '2:45:00')],
#     ...
#     }
</code>```

If you prefer a list where the info for each zone is joined in a string (like your example), then you can modify as follows.

```<code>timezones = []
for tz in all_timezones:
    tzinfos = getattr(timezone(tz), '_tzinfos', None)
    if tzinfos:
        timezones.extend([' '.join([tz, zone, str(offset)]) for offset, dst, zone in tzinfos])
    else:
        timezones.append(' '.join([tz, str(timezone(tz)._utcoffset)]))
</code>```

Per your comment regarding removing time zones with offsets that do not fall somewhere on a quarter hour interval from the output, you are probably looking to remove the various time zones that are included for historical dates (often 19th and early 20th century dates) most of which are included as some sort of "Mean Time" variation like "LMT" for "Local Mean Time". One brute force approach to removing those is just to filter out all time zone abbreviations that end in "MT" with the exception of "GMT". There are probably a few other exceptions in current use that I am unaware of but should also be handled in the same way as "GMT".

```<code>timezones = {}
for tz in all_timezones:
    tzinfos = getattr(timezone(tz), '_tzinfos', None)
    if tzinfos:
        timezones[tz] = [(zone, str(offset)) for offset, dst, zone in tzinfos if zone == 'GMT' or not zone.endswith('MT')]
    else:
        timezones[tz] = [(tz, str(timezone(tz)._utcoffset))]

print(timezones)
# {
#     'Africa/Abidjan': [('GMT', '0:00:00')],
#     'Africa/Accra': [('GMT', '0:00:00'), ('+0020', '0:20:00')],
#     'Africa/Addis_Ababa': [('EAT', '3:00:00'), ('+0230', '2:30:00'), ('+0245', '2:45:00')],
#     'Africa/Algiers': [('WET', '0:00:00'), ('WEST', '1:00:00'), ('CET', '1:00:00'), ('CEST', '2:00:00')],
#     'Africa/Asmara': [('EAT', '3:00:00'), ('+0230', '2:30:00'), ('+0245', '2:45:00')],
#     ...
#     }
</code>```

Body:
I have a Django application and I have a list of timezones hardcoded. I know pytz can be used to get a list of all timezones. But it does not show their time difference with respect to GMT. Please suggest how to get a list like this.

TIMEZONE_CHOICES = (
    ("<DstTzInfo 'Africa/Abidjan' LMT-1 day, 23:44:00 STD>", "<DstTzInfo 'Africa/Abidjan' LMT-1 day, 23:44:00 STD>"),
    ("<DstTzInfo 'Africa/Accra' LMT-1 day, 23:59:00 STD>", "<DstTzInfo 'Africa/Accra' LMT-1 day, 23:59:00 STD>"),
    ("<DstTzInfo 'Africa/Addis_Ababa' LMT+2:27:00 STD>", "<DstTzInfo 'Africa/Addis_Ababa' LMT+2:27:00 STD>"),
    ("<DstTzInfo 'Africa/Algiers' LMT+0:12:00 STD>", "<DstTzInfo 'Africa/Algiers' LMT+0:12:00 STD>"),
    ("<DstTzInfo 'Africa/Asmara' LMT+2:27:00 STD>", "<DstTzInfo 'Africa/Asmara' LMT+2:27:00 STD>"),...)

Body:
Assuming the time difference from UTC is an acceptable alternative to GMT (UTC and GMT are nearly but not exactly the same), you can get time zone offset and related information from the pytz.timezone object.

For time zones with multiple offsets (due to daylight savings, historical changes, etc), you can get the related zones and offsets from the _tzinfos attribute. For time zones with a single offset, you can get the offset from the _utcoffset attribute.

Following example creates a dict where each time zone in pytz.all_timezones is a key and the value is a list of tuples containing the related zone and offset information.

from pytz import all_timezones, timezone

timezones = {}
for tz in all_timezones:
    tzinfos = getattr(timezone(tz), '_tzinfos', None)
    if tzinfos:
        timezones[tz] = [(zone, str(offset)) for offset, dst, zone in tzinfos]
    else:
        timezones[tz] = [(tz, str(timezone(tz)._utcoffset))]

print(timezones)
# {
#     'Africa/Abidjan': [('LMT', '-1 day, 23:44:00'), ('GMT', '0:00:00')],
#     'Africa/Accra': [('LMT', '-1 day, 23:59:00'), ('GMT', '0:00:00'), ('+0020', '0:20:00')],
#     'Africa/Addis_Ababa': [('LMT', '2:27:00'), ('EAT', '3:00:00'), ('+0230', '2:30:00'), ('+0245', '2:45:00')],
#     'Africa/Algiers': [('LMT', '0:12:00'), ('PMT', '0:09:00'), ('WET', '0:00:00'), ('WEST', '1:00:00'), ('CET', '1:00:00'), ('CEST', '2:00:00')],
#     'Africa/Asmara': [('LMT', '2:27:00'), ('EAT', '3:00:00'), ('+0230', '2:30:00'), ('+0245', '2:45:00')],
#     ...
#     }

If you prefer a list where the info for each zone is joined in a string (like your example), then you can modify as follows.

timezones = []
for tz in all_timezones:
    tzinfos = getattr(timezone(tz), '_tzinfos', None)
    if tzinfos:
        timezones.extend([' '.join([tz, zone, str(offset)]) for offset, dst, zone in tzinfos])
    else:
        timezones.append(' '.join([tz, str(timezone(tz)._utcoffset)]))

Per your comment regarding removing time zones with offsets that do not fall somewhere on a quarter hour interval from the output, you are probably looking to remove the various time zones that are included for historical dates (often 19th and early 20th century dates) most of which are included as some sort of "Mean Time" variation like "LMT" for "Local Mean Time". One brute force approach to removing those is just to filter out all time zone abbreviations that end in "MT" with the exception of "GMT". There are probably a few other exceptions in current use that I am unaware of but should also be handled in the same way as "GMT".

timezones = {}
for tz in all_timezones:
    tzinfos = getattr(timezone(tz), '_tzinfos', None)
    if tzinfos:
        timezones[tz] = [(zone, str(offset)) for offset, dst, zone in tzinfos if zone == 'GMT' or not zone.endswith('MT')]
    else:
        timezones[tz] = [(tz, str(timezone(tz)._utcoffset))]

print(timezones)
# {
#     'Africa/Abidjan': [('GMT', '0:00:00')],
#     'Africa/Accra': [('GMT', '0:00:00'), ('+0020', '0:20:00')],
#     'Africa/Addis_Ababa': [('EAT', '3:00:00'), ('+0230', '2:30:00'), ('+0245', '2:45:00')],
#     'Africa/Algiers': [('WET', '0:00:00'), ('WEST', '1:00:00'), ('CET', '1:00:00'), ('CEST', '2:00:00')],
#     'Africa/Asmara': [('EAT', '3:00:00'), ('+0230', '2:30:00'), ('+0245', '2:45:00')],
#     ...
#     }


问:
material-ui v4.0.1 warning "Expected an element that can hold a ref"
I upgraded to material-ui v4.0.1 and I see that Modals now require a forwarded ref. I'm having some trouble implementing a fix for this using class components and Dialogs.

I tried using React.createRef() as well as React.forwardRef((props, ref) => (...) in a few places but I can't figure out how to resolve this warning.

In my parent component I render a custom component

```<code><ApolloFormDialog />
</code>```

In ApolloFormDialog I render essentially:

```<code><Dialog ...>
  {title}
  {subtitle}
  {form}
</Dialog>
</code>```

The full warning is Warning: Failed prop type: Invalid prop 'children' supplied to 'Modal'. Expected an element that can hold a ref. Did you accidentally use a plain function component for an element instead?

However I am using class components currently. Migrating to use function components is not an option right now as my app is rather large.

I have tried adding a ref to ApolloFormDialog as

```<code><ApolloFormDialog ref={React.createRef()} />
</code>```

as well as wrapping ApolloFormDialog's class with:

```<code>export default React.forwardRef((props, ref) => <ApolloFormDialog ref={ref} {...props}/>)
</code>```

and then adding that ref to the dialog as

```<code><Dialog ref={this.props.ref} />
</code>```

but the warning still persists, and I'm not sure where to go from here.

答:
My issue didn't actually have to do with Dialog, but with the prop TransitionComponent on Dialog.

I switch between two types of transitions in my ApolloFormDialog depending on if the screen is below a certain breakpoint, which was being called as function components:

```<code><Dialog
  open={open}
  onClose={onRequestClose}
  classes={{
    paper: classnames(classes.dialogWidth, classes.overflowVisible),
  }}
  fullScreen={fullScreen}
  TransitionComponent={
    fullScreen ? FullscreenTransition : DefaultTransition
  }
>
  {content}
</Dialog>
</code>```

FullscreenTransition and DefaultTransition come from a file and are defined as follows:

```<code>import React from 'react'
import Fade from '@material-ui/core/Fade'
import Slide from '@material-ui/core/Slide'

export function DefaultTransition(props) {
  return <Fade {...props} />
}

export function FullscreenTransition(props) {
  return <Slide direction='left' {...props} />
}

export function FullscreenExpansion(props) {
  return <Slide direction='right' {...props} />
}

</code>```

Changing these functions to the following fixed my issue:

```<code>import React from 'react'
import Fade from '@material-ui/core/Fade'
import Slide from '@material-ui/core/Slide'

export const DefaultTransition = React.forwardRef((props, ref) => (
  <Fade {...props} ref={ref} />
))

export const FullscreenTransition = React.forwardRef((props, ref) => (
  <Slide direction='left' {...props} ref={ref} />
))

export const FullscreenExpansion = React.forwardRef((props, ref) => (
  <Slide direction='right' {...props} ref={ref} />
))

</code>```

This was a relatively hard issue to solve on my end, so I'm going to leave this question up just in case someone else runs into a similar issue somewhere down the road.

Body:
I upgraded to material-ui v4.0.1 and I see that Modals now require a forwarded ref. I'm having some trouble implementing a fix for this using class components and Dialogs.

I tried using React.createRef() as well as React.forwardRef((props, ref) => (...) in a few places but I can't figure out how to resolve this warning.

In my parent component I render a custom component

<ApolloFormDialog />

In ApolloFormDialog I render essentially:

<Dialog ...>
  {title}
  {subtitle}
  {form}
</Dialog>

The full warning is Warning: Failed prop type: Invalid prop 'children' supplied to 'Modal'. Expected an element that can hold a ref. Did you accidentally use a plain function component for an element instead?

However I am using class components currently. Migrating to use function components is not an option right now as my app is rather large.

I have tried adding a ref to ApolloFormDialog as

<ApolloFormDialog ref={React.createRef()} />

as well as wrapping ApolloFormDialog's class with:

export default React.forwardRef((props, ref) => <ApolloFormDialog ref={ref} {...props}/>)

and then adding that ref to the dialog as

<Dialog ref={this.props.ref} />

but the warning still persists, and I'm not sure where to go from here.

Body:
My issue didn't actually have to do with Dialog, but with the prop TransitionComponent on Dialog.

I switch between two types of transitions in my ApolloFormDialog depending on if the screen is below a certain breakpoint, which was being called as function components:

<Dialog
  open={open}
  onClose={onRequestClose}
  classes={{
    paper: classnames(classes.dialogWidth, classes.overflowVisible),
  }}
  fullScreen={fullScreen}
  TransitionComponent={
    fullScreen ? FullscreenTransition : DefaultTransition
  }
>
  {content}
</Dialog>

FullscreenTransition and DefaultTransition come from a file and are defined as follows:

import React from 'react'
import Fade from '@material-ui/core/Fade'
import Slide from '@material-ui/core/Slide'

export function DefaultTransition(props) {
  return <Fade {...props} />
}

export function FullscreenTransition(props) {
  return <Slide direction='left' {...props} />
}

export function FullscreenExpansion(props) {
  return <Slide direction='right' {...props} />
}

Changing these functions to the following fixed my issue:

import React from 'react'
import Fade from '@material-ui/core/Fade'
import Slide from '@material-ui/core/Slide'

export const DefaultTransition = React.forwardRef((props, ref) => (
  <Fade {...props} ref={ref} />
))

export const FullscreenTransition = React.forwardRef((props, ref) => (
  <Slide direction='left' {...props} ref={ref} />
))

export const FullscreenExpansion = React.forwardRef((props, ref) => (
  <Slide direction='right' {...props} ref={ref} />
))

This was a relatively hard issue to solve on my end, so I'm going to leave this question up just in case someone else runs into a similar issue somewhere down the road.


问:
route.js routing with regular expressions
Using route.js, is it possible use a regular expression to specify routes?</p>

答:
You can’t pass a regular expression to route.js.

What you could do instead, is write just one route, route('#'), and then match the path parameter of the first parameter that’s passed to all bound routines:

```<code>route('#').bind(function (page) {
    var regex = /(.*)/,
        match = regex.exec(page.path);
    if (match) {
      alert('We matched this path: ' + match[1] + '!');
    }
});
</code>```

Be sure to check the documentation.

Body:
You can’t pass a regular expression to route.js.

What you could do instead, is write just one route, route('#'), and then match the path parameter of the first parameter that’s passed to all bound routines:

route('#').bind(function (page) {
    var regex = /(.*)/,
        match = regex.exec(page.path);
    if (match) {
      alert('We matched this path: ' + match[1] + '!');
    }
});

Be sure to check the documentation.