问:
multiple conditional renderings inside a map function
Hi there I'm looking if there's a better way to render my todos

I have this

```<code>         {
            todos.map((todo) => (

                todo.status === 1 && (
                    <p>{todo.title}</p>
                )
            ))
        }
        {
            todos.map((todo) => (
                todo.status === 2 && (
                    <p>{todo.title}</p>
                )
            ))
        }
        {
            todos.map((todo) => (
                todo.status === 3 && (
                    <p>{todo.title}</p>
                )
            ))
        }
</code>```

Is there a way to do this?

Thanks a lot

答:
Another possibility (assuming you want to e.g. put
 headings between the different types of todos) would be to use filter:

```<code>// get all todos with status 1
todos.filter(todo => todo.status === 1).map(todo => (<p key={todo.id}>{todo.title}</p>))
</code>```

 If you want to show them as a continuous array, the sort approach is better.

EDIT:
Since @epascarello insisted that more loops were bad, I wrote a quick little benchmark (takes a while before the console output starts showing up, simplified not to use React)

const REPEAT_TESTS = 1000;

function getRandomInt(max) {
  return Math.floor(Math.random() * max);
}

for (let elements of [1, 10, 100, 1000, 100000]) {
  console.warn(`trying all three approaches with ${elements} todo items`);
  const array = [];
  for (let i = 0; i < elements; i++) {
    array.push({
      title: "item " + i,
      status: getRandomInt(3) + 1
    })
  }

  // map only
  let start = performance.now();
  for (let i = 0; i < REPEAT_TESTS; i++) {
    const result1 = array.map(elem => (elem.status === 1 && elem.title));
    const result2 = array.map(elem => (elem.status === 2 && elem.title));
    const result3 = array.map(elem => (elem.status === 3 && elem.title));
  }
  let elapsed = performance.now() - start;
  console.log(`map only took ${elapsed} ms (${elapsed/REPEAT_TESTS}ms per iteration)`);

  // .filter.map()
  start = performance.now();
  for (let i = 0; i < REPEAT_TESTS; i++) {
    const result1 = array.filter(elem => elem.status === 1).map(elem => elem.title);
    const result2 = array.filter(elem => elem.status === 2).map(elem => elem.title);
    const result3 = array.filter(elem => elem.status === 3).map(elem => elem.title);
  }
  elapsed = performance.now() - start;
  console.log(`.filter().map() took ${elapsed} ms (${elapsed/REPEAT_TESTS}ms per iteration)`);

  // test 3
  start = performance.now();
  for (let i = 0; i < REPEAT_TESTS; i++) {
    const sorted = array.slice().sort((a, b) => a.status - b.status).map(elem => elem.title);
  }
  elapsed = performance.now() - start;
  console.log(`Test 3 took ${elapsed} ms (${elapsed/REPEAT_TESTS}ms per iteration)`);
}```
</div>
</div>

This clearly shows that for <code>todos.length >= 100</code></p>
<ul>
<li>OPs solution is fastest (because yes, the filter adds some loops. But OPS solution also returns <code>false</code> for all the non matching elements which is completely unusable in data processing and might incur some performance penalty in React's handling of the values)</li>
<li><code>.filter.map</code> is slightly slower but more readable and does not have the problem of returning <code>false</code> values</li>
<li><code>sort</code> is slow for more than a couple of elements and gets slower quickly. I tried this example in Nodejs with 10.000.000 elements and these were the results:</li>
</ul>
```map only took 42667.75609499961 ms (42.66775609499961ms per iteration)
.filter.map took 56544.36275900155 ms (56.54436275900155ms per iteration)
sort took 107536.24900600314 ms (107.53624900600315ms per iteration)
```

In conclusion I would always go with .filter.map chained. The benchmark also assumes the cheapest possible map function (just returning the name), for a more expensive map function the difference will be even smaller.

Body:
Hi there I'm looking if there's a better way to render my todos

I have this

         {
            todos.map((todo) => (

                todo.status === 1 && (

{todo.title}

                )
            ))
        }
        {
            todos.map((todo) => (
                todo.status === 2 && (

{todo.title}

                )
            ))
        }
        {
            todos.map((todo) => (
                todo.status === 3 && (

{todo.title}

                )
            ))
        }

Is there a way to do this?

Thanks a lot

Body:
Another possibility (assuming you want to e.g. put <h2> headings between the different types of todos) would be to use filter:

// get all todos with status 1
todos.filter(todo => todo.status === 1).map(todo => (<p key={todo.id}>{todo.title}</p>))

 If you want to show them as a continuous array, the sort approach is better.

EDIT:
Since @epascarello insisted that more loops were bad, I wrote a quick little benchmark (takes a while before the console output starts showing up, simplified not to use React)

const REPEAT_TESTS = 1000;

function getRandomInt(max) {
  return Math.floor(Math.random() * max);
}

for (let elements of [1, 10, 100, 1000, 100000]) {
  console.warn(`trying all three approaches with ${elements} todo items`);
  const array = [];
  for (let i = 0; i < elements; i++) {
    array.push({
      title: "item " + i,
      status: getRandomInt(3) + 1
    })
  }

  // map only
  let start = performance.now();
  for (let i = 0; i < REPEAT_TESTS; i++) {
    const result1 = array.map(elem => (elem.status === 1 && elem.title));
    const result2 = array.map(elem => (elem.status === 2 && elem.title));
    const result3 = array.map(elem => (elem.status === 3 && elem.title));
  }
  let elapsed = performance.now() - start;
  console.log(`map only took ${elapsed} ms (${elapsed/REPEAT_TESTS}ms per iteration)`);

  // .filter.map()
  start = performance.now();
  for (let i = 0; i < REPEAT_TESTS; i++) {
    const result1 = array.filter(elem => elem.status === 1).map(elem => elem.title);
    const result2 = array.filter(elem => elem.status === 2).map(elem => elem.title);
    const result3 = array.filter(elem => elem.status === 3).map(elem => elem.title);
  }
  elapsed = performance.now() - start;
  console.log(`.filter().map() took ${elapsed} ms (${elapsed/REPEAT_TESTS}ms per iteration)`);

  // test 3
  start = performance.now();
  for (let i = 0; i < REPEAT_TESTS; i++) {
    const sorted = array.slice().sort((a, b) => a.status - b.status).map(elem => elem.title);
  }
  elapsed = performance.now() - start;
  console.log(`Test 3 took ${elapsed} ms (${elapsed/REPEAT_TESTS}ms per iteration)`);
}

This clearly shows that for todos.length >= 100

OPs solution is fastest (because yes, the filter adds some loops. But OPS solution also returns false for all the non matching elements which is completely unusable in data processing and might incur some performance penalty in React's handling of the values)

.filter.map is slightly slower but more readable and does not have the problem of returning false values

sort is slow for more than a couple of elements and gets slower quickly. I tried this example in Nodejs with 10.000.000 elements and these were the results:

map only took 42667.75609499961 ms (42.66775609499961ms per iteration)
.filter.map took 56544.36275900155 ms (56.54436275900155ms per iteration)
sort took 107536.24900600314 ms (107.53624900600315ms per iteration)

In conclusion I would always go with .filter.map chained. The benchmark also assumes the cheapest possible map function (just returning the name), for a more expensive map function the difference will be even smaller.


来源: stackexchange

问:
Open a recordset in VS2017 like I could in VB6 for MS Access table
I am a long time VB6 guy, and feel squeezed into VS2017

I need your help with a VS2017 equivlent of

```<code>dim db as database
dim rs as recordset

db=opendatabase("path to .MDB")

rs = db.openrecordset("select * where myfield ="mine", order by fieldage")  'This SQL bit is easy.

'Then rs.movenext or rs.moveprevious etc etc

'Also it would help if I could say Textbox1.text = rs(3)
</code>```

This is to be rolled out to more than one PC, so having to set a specific data connection in the PC config is not practical.

Thanks for reading this far.

答:
I don't know if this would tick off all your needs, but it's longer than a comment, so I'm surfacing it as a possible solution.

It looks like you're doing VB.net?  I encountered a similar challenge when I converted directly from VB6 -> C# using a tool I wrote and then made public.

https://github.com/bhoogter/VB6TocSharp (Yes, I wrote this.  Yes, it's free).

To get around it, we used the standard System.Data and System.Data.OleDb packages.  These did not have the convenience methods provided like .MoveNext() or .MovePrevious(), and also, as you pointed out, could not be referenced by rs(3), let alone some of the easy positioning and filtering we were converting from.

That said, we chose to wrap the objects returned from the database calls with a Recordset class, and use those provide the interface we wanted.

Of course, the original was written in C#, available here:

https://github.com/bhoogter/VB6TocSharp/blob/master/extras/Recordset.cs

But, I put together a VB.NET port of the same, if intersted, linked, and also included here.

https://github.com/bhoogter/VB6TocSharp/blob/master/extras/vb.net/recordset.vb

Of note is the use of a few sub-classes contained within the Recordset class that can make life easier.  But, what is available right away is the methods you mentioned (MoveNext, MovePrevious, RS('fieldname'))... Note that in VB6, RS(f) would return a Field object, and the default property of that field object was .Value.  This tries to maintain back-wards compatibility by bypassing the Field object and just returning .Fields[i].Value, so you don't have to change your existing code.  This saves time and effort in conversion.  And, if there is some interface you're missing, you control this layer so you can add and/or modify as suits your conversion needs.

The VB.net ported version is as follows... It is a conversion of the C# one, so I can't guarantee it's 100% perfect, but it should be enough to demonstrate the point.  YMMV.

```<code>Imports System.Data
Imports System.Data.OleDb

' Recordset object.  Used to wrap other data objects to 'simulate' VB6.

Public Class Recordset
    Public Source As String = ""
    Public Parameters As Dictionary(Of Object, Object)
    Public Database As String = ""
    Public QuietErrors As Boolean = False

    Private mAddingRow As Boolean = False
    Public ReadOnly Property AddingRow As Boolean
        Get
            Return mAddingRow
        End Get
    End Property

    Private connection As OleDbConnection
    Private adapter As OleDbDataAdapter
    Private table As DataTable
    Private filteredTable As DataTable
    Private mFilter As String

    Public Sub New()

    End Sub
    Public Sub New(table As DataTable, adapter As OleDbDataAdapter, connection As OleDbConnection)
        Me.connection = connection
        Me.adapter = adapter
        Me.table = table
    End Sub

    Public Sub New(SQL As String, File As String, Optional QuietErrors As Boolean = False, Optional Parameters As Dictionary(Of Object, Object) = Nothing)
        Me.Source = SQL
        Me.Parameters = Parameters
        Me.Database = File
        Me.QuietErrors = QuietErrors

        Open()
    End Sub

    Public Sub Close()
        Try
            connection?.Close()
        Catch
            ' just suppress
        End Try

        connection = Nothing
        adapter = Nothing
        table = Nothing
        filteredTable = Nothing
    End Sub

    Public Shared Sub sqlExecutionError(mSQL As String, e As Exception)
        Dim T As String = ""
        T &= "getRecordSet Failed: " & e.Message & vbCrLf
        T &= vbCrLf
        T &= mSQL & vbCrLf
        T &= vbCrLf
        T &= "ERROR:" & e.Message

        T = T.Replace("$EDESC", e.Message)
        'ErrMsg = Replace(ErrMsg, "$ENO", Err().Number)
        T = T.Replace("$ESRC", e.Source)
        MsgBox("Database Error: " + T, 0, "Error")
        'CheckStandardErrors() ' Bookmark/updateable query
    End Sub

    Private Function ConnectionString(file As String) As String
        Return "PROVIDER=Microsoft.Jet.OLEDB.4.0Data Source=" + file
    End Function

    Public Property AbsolutePosition As Integer = -1
    Public Property Position As Integer
        Get
            Return AbsolutePosition
        End Get
        Set(value As Integer)
            AbsolutePosition = value
        End Set
    End Property
    Public ReadOnly Property RecordCount As Integer
        Get
            If Not table Is Nothing Then
                If Not table.Rows Is Nothing Then
                    Return table.Rows.Count
                End If
            End If
            Return 0
        End Get
    End Property
    Public ReadOnly Property EOF As Boolean
        Get
            Return AbsolutePosition >= RecordCount
        End Get
    End Property
    Public ReadOnly Property BOF As Boolean
        Get
            Return AbsolutePosition = 0
        End Get
    End Property

    Public Function FieldExists(F As String) As Boolean
        If Not table Is Nothing Then
            If Not table.Columns Is Nothing Then
                Return table.Columns.Contains(F)
            End If
        End If
        Return False
    End Function

    Public Function MoveFirst() As Integer
        AbsolutePosition = 0
        Return 0
    End Function
    Public Function MoveNext() As Integer
        Return If(++AbsolutePosition < RecordCount, AbsolutePosition, AbsolutePosition = RecordCount)
    End Function
    Public Function MovePrevious() As Integer
        Return If(--AbsolutePosition >= 0, AbsolutePosition, AbsolutePosition = 0)
    End Function
    Public Function MoveLast() As Integer
        AbsolutePosition = RecordCount - 1
        Return AbsolutePosition
    End Function

    Public ReadOnly Property Fields As RecordsetFields
        Get
            If AbsolutePosition >= 0 And AbsolutePosition < RecordCount Then Return New RecordsetFields(table.Rows(AbsolutePosition))
            Throw New ArgumentOutOfRangeException("Either EOF or BOF is true.")
        End Get
    End Property

    Public ReadOnly Property FieldNames As List(Of String)
        Get
            If IsNothing(table) Then Return Nothing
            Dim result As List(Of String) = New List(Of String)
            For Each item As DataColumn In table.Columns
                result.Add(item.ColumnName)
            Next
            Return result
        End Get
    End Property

    Public ReadOnly Property Field As PropIndexer(Of Object, Object)
        Get
            Return New PropIndexer(Of Object, Object)(
                Function(k As Object)
                    Return Fields(k).Value
                End Function,
                Function(k As Object, v As Object)
                    Fields(k).Value = v
                End Function
                )
        End Get
    End Property

    Default Property Item(field As Object) As Object
        Get
            Return GetField(field)
        End Get
        Set
            SetField(field, Value)
        End Set
    End Property

    Public Function GetField(key As Object) As Object
        Return Fields(key).Value
    End Function
    Public Sub SetField(key As Object, value As Object)
        Fields(key).Value = value
    End Sub

    Public Function GetRows() As List(Of List(Of Object))
        Dim tableEnumerable As Object = table.AsEnumerable()
        Dim tableList As Object = tableEnumerable.ToArray().ToList()
        Return tableList.ToList() _
        .Select(Function(r As Object)
                    Return r.ItemArray.ToList()
                End Function) _
        .ToList()
    End Function

    Public Property Filter As String
        Get
            Return mFilter
        End Get
        Set(value As String)
            mFilter = value
            If String.IsNullOrEmpty(value) Then
                filteredTable = Nothing
                Return
            End If

            filteredTable = table.Select(mFilter).CopyToDataTable()
        End Set
    End Property

    Protected Function Find(v As String) As Boolean
        Dim temp As DataTable = table.Select(mFilter).CopyToDataTable()
        If temp.Rows.Count = 0 Then Return False
        Dim X As Integer = table.Rows.IndexOf(temp.Rows(0))
        AbsolutePosition = X
        Return True
    End Function

    Private Sub Open()
        Const maxTries = 5

        If Dir(Database) = "" Then
            MsgBox("Database Not Found: " + Database)
            Return
        End If

        Dim result As DataSet = New DataSet()
        connection = New OleDbConnection(ConnectionString(Database))
        Dim Command As OleDbCommand = New OleDbCommand(Source, connection)
        For Each Key In Parameters.Keys
            Dim param As OleDbParameter = Command.CreateParameter()
            param.ParameterName = Key
            param.Value = Parameters(Key)
        Next

        adapter = New OleDbDataAdapter(Command)
        Try
            connection.Open()
            adapter.FillSchema(result, SchemaType.Source)
            adapter.Fill(result, "Default")
        Catch e As Exception
            If Not QuietErrors Then sqlExecutionError(Source, e)
        Finally
            connection.Close()
        End Try

        table = result.Tables("Default")
    End Sub

    Public Sub Update()
        Dim cb As OleDbCommandBuilder = New OleDbCommandBuilder(adapter)
        cb.QuotePrefix = "["
        cb.QuoteSuffix = "]"
        Try
            connection.Open()
            adapter.UpdateCommand = cb.GetUpdateCommand()
            adapter.Update(table)
        Catch e As Exception
            If Not QuietErrors Then sqlExecutionError(adapter.DeleteCommand.ToString(), e)
        Finally
            connection.Close()
        End Try

        mAddingRow = False
    End Sub

    Public Sub AddNew()
        Dim newRow As DataRow = table.NewRow()
        table.Rows.InsertAt(newRow, table.Rows.Count)
        AbsolutePosition = table.Rows.Count - 1
        mAddingRow = True
    End Sub

    Public Sub Delete()
        Dim cb As OleDbCommandBuilder = New OleDbCommandBuilder(adapter)
        Try
            connection.Open()
            adapter.DeleteCommand = cb.GetDeleteCommand()
            adapter.Update(table)
        Catch e As Exception
            If Not QuietErrors Then sqlExecutionError(adapter.UpdateCommand.ToString(), e)
        Finally
            connection.Close()
        End Try
    End Sub

    Public Class RecordsetFields
        Implements ICollection
        Private row As DataRow = Nothing

        Public Sub New(row As DataRow)
            Me.row = row
        End Sub

        Public ReadOnly Property Count As Integer
            Get
                Return row.Table.Columns.Count
            End Get
        End Property
        Public SyncRoot As Object = Nothing
        Public IsSynchronized As Boolean = False

        Private Sub ICollection_CopyTo(array As Array, index As Integer) Implements ICollection.CopyTo
            Throw New InvalidOperationException("Not valid on object")
        End Sub

        Private Function IEnumerable_GetEnumerator() As IEnumerator Implements IEnumerable.GetEnumerator
            Return row.Table.Columns.GetEnumerator()
        End Function

        Default Public ReadOnly Property Item(x As Object) As RecordsetField
            Get
                Dim C As DataColumn = row.Table.Columns(x)
                Return New RecordsetField(row, x)
            End Get
        End Property

        Private ReadOnly Property ICollection_Count As Integer Implements ICollection.Count
            Get
                Throw New NotImplementedException()
            End Get
        End Property

        Private ReadOnly Property ICollection_IsSynchronized As Boolean Implements ICollection.IsSynchronized
            Get
                Throw New NotImplementedException()
            End Get
        End Property

        Private ReadOnly Property ICollection_SyncRoot As Object Implements ICollection.SyncRoot
            Get
                Throw New NotImplementedException()
            End Get
        End Property
    End Class

    Public Class RecordsetField
        Public Const adSmallInt As Integer = 2 ' Integer    SmallInt
        Public Const adInteger As Integer = 3 ' AutoNumber
        Public Const adSingle As Integer = 4 ' Single   Real
        Public Const adDouble As Integer = 5 ' Double   Float   Float
        Public Const adCurrency As Integer = 6 ' Currency   Money
        Public Const adDate As Integer = 7 ' Date   DateTime
        Public Const adIDispatch As Integer = 9 '
        Public Const adBoolean As Integer = 11 '    YesNo   Bit
        Public Const adVariant As Integer = 12 ' Sql_Variant(SQL Server 2000 +) VarChar2
        Public Const adDecimal As Integer = 14 ' Decimal *
        Public Const adUnsignedTinyInt As Integer = 17 '    Byte    TinyInt
        Public Const adBigInt As Integer = 20 ' BigInt(SQL Server 2000 +)
        Public Const adGUID As Integer = 72 ' ReplicationID(Access 97 (OLEDB)), (Access 2000 (OLEDB))   UniqueIdentifier (SQL Server 7.0 +)
        Public Const adWChar As Integer = 130 ' NChar(SQL Server 7.0 +)
        Public Const adChar As Integer = 129 ' Char Char
        Public Const adNumeric As Integer = 131 ' Decimal(Access 2000 (OLEDB))  Decimal
        Public Const adBinary As Integer = 128 ' Binary
        Public Const adDBTimeStamp As Integer = 135 ' DateTime(Access 97 (ODBC))    DateTime
        Public Const adVarChar As Integer = 200 ' Text(Access 97)   VarChar VarChar
        Public Const adLongVarChar As Integer = 201 ' Memo(Access 97)
        Public Const adVarWChar As Integer = 202 ' Text(Access 2000 (OLEDB))    NVarChar (SQL Server 7.0 +) NVarChar2
        Public Const adLongVarWChar As Integer = 203 ' Memo(Access 2000 (OLEDB))
        Public Const adVarBinary As Integer = 204 ' ReplicationID(Access 97)    VarBinary
        Public Const adLongVarBinary As Integer = 205 ' OLEObject   Image   Long Raw *

        Private Row As DataRow = Nothing
        Public Name As Object = ""
        Public Size As Integer = 0

        Public Sub New(Row As DataRow, Name As Object)
            Me.Row = Row
            Me.Name = Name
        End Sub

        Public Property Value As Object
            Get
                Return Row(Name)
            End Get
            Set(value As Object)
                Row(Name) = value
            End Set
        End Property

        Public ReadOnly Property Type As Object
            Get
                Return Row.Table.Columns(Name).DataType
            End Get
        End Property
    End Class

    Public Class PropIndexer(Of I, V)
        Public Delegate Sub setProperty(idx As I, value As V)
        Public Delegate Function getProperty(idx As I)

        Public getter As getProperty
        Public setter As setProperty

        Public Sub New(g As getProperty, s As setProperty)
            getter = g
            setter = s
        End Sub
        Public Sub New(g As getProperty)
            getter = g
            setter = AddressOf setPropertyNoop
        End Sub
        Public Sub New()
            getter = AddressOf getPropertyNoop
            setter = AddressOf setPropertyNoop
        End Sub

        Private Sub setPropertyNoop(idx As I, value As V)
            ' NOOP.  Intentionally left blank.
        End Sub
        Private Function getPropertyNoop(idx As I) As V
            Return CType(Nothing, V)
        End Function

        Default Public Property Item(ByVal nIndex As I) As V
            Get
                Return getter.Invoke(nIndex)

            End Get
            Set
                setter.Invoke(nIndex, Value)
            End Set
        End Property
    End Class

End Class
</code>```

ContentLicense: CC BY-SA 4.0

Body:
I am a long time VB6 guy, and feel squeezed into VS2017

I need your help with a VS2017 equivlent of

dim db as database
dim rs as recordset

db=opendatabase("path to .MDB")

rs = db.openrecordset("select * where myfield ="mine", order by fieldage")  'This SQL bit is easy.

'Then rs.movenext or rs.moveprevious etc etc

'Also it would help if I could say Textbox1.text = rs(3)

This is to be rolled out to more than one PC, so having to set a specific data connection in the PC config is not practical.

Thanks for reading this far.

Body:
I don't know if this would tick off all your needs, but it's longer than a comment, so I'm surfacing it as a possible solution.

It looks like you're doing VB.net?  I encountered a similar challenge when I converted directly from VB6 -> C# using a tool I wrote and then made public.

https://github.com/bhoogter/VB6TocSharp (Yes, I wrote this.  Yes, it's free).

To get around it, we used the standard System.Data and System.Data.OleDb packages.  These did not have the convenience methods provided like .MoveNext() or .MovePrevious(), and also, as you pointed out, could not be referenced by rs(3), let alone some of the easy positioning and filtering we were converting from.

That said, we chose to wrap the objects returned from the database calls with a Recordset class, and use those provide the interface we wanted.

Of course, the original was written in C#, available here:

https://github.com/bhoogter/VB6TocSharp/blob/master/extras/Recordset.cs

But, I put together a VB.NET port of the same, if intersted, linked, and also included here.

https://github.com/bhoogter/VB6TocSharp/blob/master/extras/vb.net/recordset.vb

Of note is the use of a few sub-classes contained within the Recordset class that can make life easier.  But, what is available right away is the methods you mentioned (MoveNext, MovePrevious, RS('fieldname'))... Note that in VB6, RS(f) would return a Field object, and the default property of that field object was .Value.  This tries to maintain back-wards compatibility by bypassing the Field object and just returning .Fields[i].Value, so you don't have to change your existing code.  This saves time and effort in conversion.  And, if there is some interface you're missing, you control this layer so you can add and/or modify as suits your conversion needs.

The VB.net ported version is as follows... It is a conversion of the C# one, so I can't guarantee it's 100% perfect, but it should be enough to demonstrate the point.  YMMV.

Imports System.Data
Imports System.Data.OleDb

' Recordset object.  Used to wrap other data objects to 'simulate' VB6.

Public Class Recordset
    Public Source As String = ""
    Public Parameters As Dictionary(Of Object, Object)
    Public Database As String = ""
    Public QuietErrors As Boolean = False

    Private mAddingRow As Boolean = False
    Public ReadOnly Property AddingRow As Boolean
        Get
            Return mAddingRow
        End Get
    End Property

    Private connection As OleDbConnection
    Private adapter As OleDbDataAdapter
    Private table As DataTable
    Private filteredTable As DataTable
    Private mFilter As String

    Public Sub New()

    End Sub
    Public Sub New(table As DataTable, adapter As OleDbDataAdapter, connection As OleDbConnection)
        Me.connection = connection
        Me.adapter = adapter
        Me.table = table
    End Sub

    Public Sub New(SQL As String, File As String, Optional QuietErrors As Boolean = False, Optional Parameters As Dictionary(Of Object, Object) = Nothing)
        Me.Source = SQL
        Me.Parameters = Parameters
        Me.Database = File
        Me.QuietErrors = QuietErrors

        Open()
    End Sub

    Public Sub Close()
        Try
            connection?.Close()
        Catch
            ' just suppress
        End Try

        connection = Nothing
        adapter = Nothing
        table = Nothing
        filteredTable = Nothing
    End Sub

    Public Shared Sub sqlExecutionError(mSQL As String, e As Exception)
        Dim T As String = ""
        T &= "getRecordSet Failed: " & e.Message & vbCrLf
        T &= vbCrLf
        T &= mSQL & vbCrLf
        T &= vbCrLf
        T &= "ERROR:" & e.Message

        T = T.Replace("$EDESC", e.Message)
        'ErrMsg = Replace(ErrMsg, "$ENO", Err().Number)
        T = T.Replace("$ESRC", e.Source)
        MsgBox("Database Error: " + T, 0, "Error")
        'CheckStandardErrors() ' Bookmark/updateable query
    End Sub

    Private Function ConnectionString(file As String) As String
        Return "PROVIDER=Microsoft.Jet.OLEDB.4.0Data Source=" + file
    End Function

    Public Property AbsolutePosition As Integer = -1
    Public Property Position As Integer
        Get
            Return AbsolutePosition
        End Get
        Set(value As Integer)
            AbsolutePosition = value
        End Set
    End Property
    Public ReadOnly Property RecordCount As Integer
        Get
            If Not table Is Nothing Then
                If Not table.Rows Is Nothing Then
                    Return table.Rows.Count
                End If
            End If
            Return 0
        End Get
    End Property
    Public ReadOnly Property EOF As Boolean
        Get
            Return AbsolutePosition >= RecordCount
        End Get
    End Property
    Public ReadOnly Property BOF As Boolean
        Get
            Return AbsolutePosition = 0
        End Get
    End Property

    Public Function FieldExists(F As String) As Boolean
        If Not table Is Nothing Then
            If Not table.Columns Is Nothing Then
                Return table.Columns.Contains(F)
            End If
        End If
        Return False
    End Function

    Public Function MoveFirst() As Integer
        AbsolutePosition = 0
        Return 0
    End Function
    Public Function MoveNext() As Integer
        Return If(++AbsolutePosition < RecordCount, AbsolutePosition, AbsolutePosition = RecordCount)
    End Function
    Public Function MovePrevious() As Integer
        Return If(--AbsolutePosition >= 0, AbsolutePosition, AbsolutePosition = 0)
    End Function
    Public Function MoveLast() As Integer
        AbsolutePosition = RecordCount - 1
        Return AbsolutePosition
    End Function

    Public ReadOnly Property Fields As RecordsetFields
        Get
            If AbsolutePosition >= 0 And AbsolutePosition < RecordCount Then Return New RecordsetFields(table.Rows(AbsolutePosition))
            Throw New ArgumentOutOfRangeException("Either EOF or BOF is true.")
        End Get
    End Property

    Public ReadOnly Property FieldNames As List(Of String)
        Get
            If IsNothing(table) Then Return Nothing
            Dim result As List(Of String) = New List(Of String)
            For Each item As DataColumn In table.Columns
                result.Add(item.ColumnName)
            Next
            Return result
        End Get
    End Property

    Public ReadOnly Property Field As PropIndexer(Of Object, Object)
        Get
            Return New PropIndexer(Of Object, Object)(
                Function(k As Object)
                    Return Fields(k).Value
                End Function,
                Function(k As Object, v As Object)
                    Fields(k).Value = v
                End Function
                )
        End Get
    End Property

    Default Property Item(field As Object) As Object
        Get
            Return GetField(field)
        End Get
        Set
            SetField(field, Value)
        End Set
    End Property

    Public Function GetField(key As Object) As Object
        Return Fields(key).Value
    End Function
    Public Sub SetField(key As Object, value As Object)
        Fields(key).Value = value
    End Sub

    Public Function GetRows() As List(Of List(Of Object))
        Dim tableEnumerable As Object = table.AsEnumerable()
        Dim tableList As Object = tableEnumerable.ToArray().ToList()
        Return tableList.ToList() _
        .Select(Function(r As Object)
                    Return r.ItemArray.ToList()
                End Function) _
        .ToList()
    End Function

    Public Property Filter As String
        Get
            Return mFilter
        End Get
        Set(value As String)
            mFilter = value
            If String.IsNullOrEmpty(value) Then
                filteredTable = Nothing
                Return
            End If

            filteredTable = table.Select(mFilter).CopyToDataTable()
        End Set
    End Property

    Protected Function Find(v As String) As Boolean
        Dim temp As DataTable = table.Select(mFilter).CopyToDataTable()
        If temp.Rows.Count = 0 Then Return False
        Dim X As Integer = table.Rows.IndexOf(temp.Rows(0))
        AbsolutePosition = X
        Return True
    End Function

    Private Sub Open()
        Const maxTries = 5

        If Dir(Database) = "" Then
            MsgBox("Database Not Found: " + Database)
            Return
        End If

        Dim result As DataSet = New DataSet()
        connection = New OleDbConnection(ConnectionString(Database))
        Dim Command As OleDbCommand = New OleDbCommand(Source, connection)
        For Each Key In Parameters.Keys
            Dim param As OleDbParameter = Command.CreateParameter()
            param.ParameterName = Key
            param.Value = Parameters(Key)
        Next

        adapter = New OleDbDataAdapter(Command)
        Try
            connection.Open()
            adapter.FillSchema(result, SchemaType.Source)
            adapter.Fill(result, "Default")
        Catch e As Exception
            If Not QuietErrors Then sqlExecutionError(Source, e)
        Finally
            connection.Close()
        End Try

        table = result.Tables("Default")
    End Sub

    Public Sub Update()
        Dim cb As OleDbCommandBuilder = New OleDbCommandBuilder(adapter)
        cb.QuotePrefix = "["
        cb.QuoteSuffix = "]"
        Try
            connection.Open()
            adapter.UpdateCommand = cb.GetUpdateCommand()
            adapter.Update(table)
        Catch e As Exception
            If Not QuietErrors Then sqlExecutionError(adapter.DeleteCommand.ToString(), e)
        Finally
            connection.Close()
        End Try

        mAddingRow = False
    End Sub

    Public Sub AddNew()
        Dim newRow As DataRow = table.NewRow()
        table.Rows.InsertAt(newRow, table.Rows.Count)
        AbsolutePosition = table.Rows.Count - 1
        mAddingRow = True
    End Sub

    Public Sub Delete()
        Dim cb As OleDbCommandBuilder = New OleDbCommandBuilder(adapter)
        Try
            connection.Open()
            adapter.DeleteCommand = cb.GetDeleteCommand()
            adapter.Update(table)
        Catch e As Exception
            If Not QuietErrors Then sqlExecutionError(adapter.UpdateCommand.ToString(), e)
        Finally
            connection.Close()
        End Try
    End Sub

    Public Class RecordsetFields
        Implements ICollection
        Private row As DataRow = Nothing

        Public Sub New(row As DataRow)
            Me.row = row
        End Sub

        Public ReadOnly Property Count As Integer
            Get
                Return row.Table.Columns.Count
            End Get
        End Property
        Public SyncRoot As Object = Nothing
        Public IsSynchronized As Boolean = False

        Private Sub ICollection_CopyTo(array As Array, index As Integer) Implements ICollection.CopyTo
            Throw New InvalidOperationException("Not valid on object")
        End Sub

        Private Function IEnumerable_GetEnumerator() As IEnumerator Implements IEnumerable.GetEnumerator
            Return row.Table.Columns.GetEnumerator()
        End Function

        Default Public ReadOnly Property Item(x As Object) As RecordsetField
            Get
                Dim C As DataColumn = row.Table.Columns(x)
                Return New RecordsetField(row, x)
            End Get
        End Property

        Private ReadOnly Property ICollection_Count As Integer Implements ICollection.Count
            Get
                Throw New NotImplementedException()
            End Get
        End Property

        Private ReadOnly Property ICollection_IsSynchronized As Boolean Implements ICollection.IsSynchronized
            Get
                Throw New NotImplementedException()
            End Get
        End Property

        Private ReadOnly Property ICollection_SyncRoot As Object Implements ICollection.SyncRoot
            Get
                Throw New NotImplementedException()
            End Get
        End Property
    End Class

    Public Class RecordsetField
        Public Const adSmallInt As Integer = 2 ' Integer    SmallInt
        Public Const adInteger As Integer = 3 ' AutoNumber
        Public Const adSingle As Integer = 4 ' Single   Real
        Public Const adDouble As Integer = 5 ' Double   Float   Float
        Public Const adCurrency As Integer = 6 ' Currency   Money
        Public Const adDate As Integer = 7 ' Date   DateTime
        Public Const adIDispatch As Integer = 9 '
        Public Const adBoolean As Integer = 11 '    YesNo   Bit
        Public Const adVariant As Integer = 12 ' Sql_Variant(SQL Server 2000 +) VarChar2
        Public Const adDecimal As Integer = 14 ' Decimal *
        Public Const adUnsignedTinyInt As Integer = 17 '    Byte    TinyInt
        Public Const adBigInt As Integer = 20 ' BigInt(SQL Server 2000 +)
        Public Const adGUID As Integer = 72 ' ReplicationID(Access 97 (OLEDB)), (Access 2000 (OLEDB))   UniqueIdentifier (SQL Server 7.0 +)
        Public Const adWChar As Integer = 130 ' NChar(SQL Server 7.0 +)
        Public Const adChar As Integer = 129 ' Char Char
        Public Const adNumeric As Integer = 131 ' Decimal(Access 2000 (OLEDB))  Decimal
        Public Const adBinary As Integer = 128 ' Binary
        Public Const adDBTimeStamp As Integer = 135 ' DateTime(Access 97 (ODBC))    DateTime
        Public Const adVarChar As Integer = 200 ' Text(Access 97)   VarChar VarChar
        Public Const adLongVarChar As Integer = 201 ' Memo(Access 97)
        Public Const adVarWChar As Integer = 202 ' Text(Access 2000 (OLEDB))    NVarChar (SQL Server 7.0 +) NVarChar2
        Public Const adLongVarWChar As Integer = 203 ' Memo(Access 2000 (OLEDB))
        Public Const adVarBinary As Integer = 204 ' ReplicationID(Access 97)    VarBinary
        Public Const adLongVarBinary As Integer = 205 ' OLEObject   Image   Long Raw *

        Private Row As DataRow = Nothing
        Public Name As Object = ""
        Public Size As Integer = 0

        Public Sub New(Row As DataRow, Name As Object)
            Me.Row = Row
            Me.Name = Name
        End Sub

        Public Property Value As Object
            Get
                Return Row(Name)
            End Get
            Set(value As Object)
                Row(Name) = value
            End Set
        End Property

        Public ReadOnly Property Type As Object
            Get
                Return Row.Table.Columns(Name).DataType
            End Get
        End Property
    End Class

    Public Class PropIndexer(Of I, V)
        Public Delegate Sub setProperty(idx As I, value As V)
        Public Delegate Function getProperty(idx As I)

        Public getter As getProperty
        Public setter As setProperty

        Public Sub New(g As getProperty, s As setProperty)
            getter = g
            setter = s
        End Sub
        Public Sub New(g As getProperty)
            getter = g
            setter = AddressOf setPropertyNoop
        End Sub
        Public Sub New()
            getter = AddressOf getPropertyNoop
            setter = AddressOf setPropertyNoop
        End Sub

        Private Sub setPropertyNoop(idx As I, value As V)
            ' NOOP.  Intentionally left blank.
        End Sub
        Private Function getPropertyNoop(idx As I) As V
            Return CType(Nothing, V)
        End Function

        Default Public Property Item(ByVal nIndex As I) As V
            Get
                Return getter.Invoke(nIndex)

            End Get
            Set
                setter.Invoke(nIndex, Value)
            End Set
        End Property
    End Class

End Class


问:
How to generate combinations of elements of different lists?
I have a list of lists that goes like

```<code>[[1,2,3],[3,4,5],[5,6,7,8]]
</code>```

I want to create a program/function that creates a combinations like

```<code>1,3,5
1,3,6
1,3,7
1,3,8
1,4,5
1,4,6
.
.
.
</code>```

If there's a way you can do it without using the itertools module, that would be even more appreciated.

答:
I tried two different ways, straight list comprehension and a recursive function.

The list comprehension method is the simplest but assumes your list will only have 3 elements.  If you add a fourth set of numbers to your main list, the list comprehension will need to be adjusted to work with it.

In contrast the recursive function is more complicated but will handle an unlimited list of lists with the sub-lists having any number of elements.  Of course, it's recursive so a limit will be reached and the time it takes to process the list of lists will be exponentially greater with each additonal list of numbers.

List Comprehension

lol = [
    [1,2,3],
    [3,4,5],
    [5,6,7,8]
]
o = [[x, y, z] for x in lol[0] for y in lol[1] for z in lol[2]]
print(repr(o))
```
<h2>output</h2>
<pre class="lang-py prettyprint-override"><code>[
  [1, 3, 5],
  [1, 3, 6],
  [1, 3, 7],
  [1, 3, 8],
  [1, 4, 5],
  ...
  [3, 5, 6],
  [3, 5, 7],
  [3, 5, 8]
]
</code>```

Recursive function

def stich(l: list) -> list:
    def merge(a, b):
        if not a:
            return [[y,] for y in b]
        return [x + [y,] for x in a for y in b]
    ol = []
    tl = l.copy()
    while tl:
        ol = merge(ol, tl.pop(0))
    return ol

stiched_list = stich(lol)
print(repr(stiched_list))
```
<h2>output</h2>
<pre class="lang-py prettyprint-override"><code>[
  [1, 3, 5],
  [1, 3, 6],
  [1, 3, 7],
  [1, 3, 8],
  [1, 4, 5],
  ...
  [3, 5, 6],
  [3, 5, 7],
  [3, 5, 8]
]
</code>```

Body:
I have a list of lists that goes like

[[1,2,3],[3,4,5],[5,6,7,8]]

I want to create a program/function that creates a combinations like

1,3,5
1,3,6
1,3,7
1,3,8
1,4,5
1,4,6
.
.
.

If there's a way you can do it without using the itertools module, that would be even more appreciated.

Body:
I tried two different ways, straight list comprehension and a recursive function.

The list comprehension method is the simplest but assumes your list will only have 3 elements.  If you add a fourth set of numbers to your main list, the list comprehension will need to be adjusted to work with it.

In contrast the recursive function is more complicated but will handle an unlimited list of lists with the sub-lists having any number of elements.  Of course, it's recursive so a limit will be reached and the time it takes to process the list of lists will be exponentially greater with each additonal list of numbers.

List Comprehension

lol = [
    [1,2,3],
    [3,4,5],
    [5,6,7,8]
]
o = [[x, y, z] for x in lol[0] for y in lol[1] for z in lol[2]]
print(repr(o))

output

[
  [1, 3, 5],
  [1, 3, 6],
  [1, 3, 7],
  [1, 3, 8],
  [1, 4, 5],
  ...
  [3, 5, 6],
  [3, 5, 7],
  [3, 5, 8]
]

Recursive function

def stich(l: list) -> list:
    def merge(a, b):
        if not a:
            return [[y,] for y in b]
        return [x + [y,] for x in a for y in b]
    ol = []
    tl = l.copy()
    while tl:
        ol = merge(ol, tl.pop(0))
    return ol

stiched_list = stich(lol)
print(repr(stiched_list))

output

[
  [1, 3, 5],
  [1, 3, 6],
  [1, 3, 7],
  [1, 3, 8],
  [1, 4, 5],
  ...
  [3, 5, 6],
  [3, 5, 7],
  [3, 5, 8]
]


问:
Problem looping through web controls
I've got a web page where I am dynamically creating controls during Page_Load event (this is done so because I do not know how many controls I will need until session is active and certain variables are accessible)

I need to be able to loop through these controls to find Checkbox when a button click is processed. Looping through the Form.Controls does not appear to be sufficient. I would think that Request.Form might work but it does not appear to be accessible in my C# block?

What should code for Request.Form look like? OR

Has anyone done this before with dynamically created controls?

Any insight is appreciated.

答:
Simplified Example from MSDN:

```<code>var myControl = FindControl("NameOfControl");
if(myControl != null)
{
   //do something
}
else
{
   //control not found
}
</code>```

Hope this helps! ;)

ContentLicense: CC BY-SA 3.0

Title: Problem looping through web controls

Body:
Simplified Example from MSDN:

var myControl = FindControl("NameOfControl");
if(myControl != null)
{
   //do something
}
else
{
   //control not found
}

Hope this helps! ;)


问:
Get an object of multiple person first and last name comma separeted
So in my JS I have 3 variables like so;

```<code>fName = 'Lili, Abraham';
lName = 'Vabiens, Lincoln';
email = 'l@vbiens.com, a@lcln.com'
</code>```

And I'd like to get an object of the person details like so.

So, in the end, I'd have this:

```<code>{ firstName: "Lily", lastName: "Vabiens", fullName: : "Lily Vabiens", email: "l@vbiens.com" },
{ firstName: "Abraham", lastName: "Lincoln", fullName: : "Abraham Lincoln", email: "a@lcln.com" },
</code>```

What would be the smartest way of going about this?

答:
Now considering the lengths of each attribute of data is same, the following code will work.

First we split the strings into arrays.

```<code>fName = 'Lili, Abraham';
lName = 'Vabiens, Lincoln';
email = 'l@vbiens.com, a@lcln.com'

f_name_list = fName.split(', ');
l_name_list = lName.split(', ');
email_list = email.split(', ');
</code>```

Then we loop and append an object to an array.

```<code>let result = [];

for ( let i = 0; i < f_name_list.length; i++ ) {
  result.push({
    firstName: f_name_list[i],
    lastName: l_name_list[i],
    fullName: f_name_list[i] + ' ' + l_name_list[i],
    email: email_list[i]
  });
}
</code>```

Body:
So in my JS I have 3 variables like so;

fName = 'Lili, Abraham';
lName = 'Vabiens, Lincoln';
email = 'l@vbiens.com, a@lcln.com'

And I'd like to get an object of the person details like so.

So, in the end, I'd have this:

{ firstName: "Lily", lastName: "Vabiens", fullName: : "Lily Vabiens", email: "l@vbiens.com" },
{ firstName: "Abraham", lastName: "Lincoln", fullName: : "Abraham Lincoln", email: "a@lcln.com" },

What would be the smartest way of going about this?

Body:
Now considering the lengths of each attribute of data is same, the following code will work.

First we split the strings into arrays.

fName = 'Lili, Abraham';
lName = 'Vabiens, Lincoln';
email = 'l@vbiens.com, a@lcln.com'

f_name_list = fName.split(', ');
l_name_list = lName.split(', ');
email_list = email.split(', ');

Then we loop and append an object to an array.

let result = [];

for ( let i = 0; i < f_name_list.length; i++ ) {
  result.push({
    firstName: f_name_list[i],
    lastName: l_name_list[i],
    fullName: f_name_list[i] + ' ' + l_name_list[i],
    email: email_list[i]
  });
}


问:
PHP 7.2 Warning count(): Parameter must be an array or an object that implements Countable
i've a problem with Wordpress. This is the error message: PHP 7.2 Warning count(): Parameter must be an array or an object that implements Countable /web/htdocs/www.firenzeflowershow.com/home/wp-content/themes/wpex-elegant/functions/meta/init.php on line 750</p>
```<code>> elseif ( is_array( $meta_box['pages'] ) && count( $meta_box['pages']
> === 1  ))             $type = is_string( end( $meta_box['pages'] ) ) ? end( $meta_box['pages'] ) : false;
</code>```

答:
The closing parenthesis of count is in the wrong position. You are actually passing a boolean to the function, because "$meta_box['pages'] === 1" will return true or false. Your code should be:

```<code>count($meta_box['pages']) === 1
</code>```

Body:
i've a problem with Wordpress. This is the error message: PHP 7.2 Warning count(): Parameter must be an array or an object that implements Countable /web/htdocs/www.firenzeflowershow.com/home/wp-content/themes/wpex-elegant/functions/meta/init.php on line 750

> elseif ( is_array( $meta_box['pages'] ) && count( $meta_box['pages']
> === 1  ))             $type = is_string( end( $meta_box['pages'] ) ) ? end( $meta_box['pages'] ) : false;

Body:
The closing parenthesis of count is in the wrong position. You are actually passing a boolean to the function, because "$meta_box['pages'] === 1" will return true or false. Your code should be:

count($meta_box['pages']) === 1


问:
Does the memory map of a structure change whether there is a pointer or namespace difference?
I am looking to write a firmware that writes a structure to and reads it back from EEPROM memory. Converting the structure into a byte stream is working, however when I abstract the problem by putting the structure into a namespace, or call functions that pass pointers to the structure, the byte offsets seem to change by multiples of 2.

To create the memory map of the structure I am using the methods:

```<code>template <typename U>
void StoreStruct(U *structure, unsigned int location) {
  byte values[sizeof(U)];
  memcpy(values, structure, sizeof(U));
  ...
}

template <typename U>
void RetrieveStruct(U *result, unsigned int location) {
  byte readValues[sizeof(U)];
  ...
  memcpy(result, readValues, sizeof(U));
}
</code>```

When calling these from a common namespace, they function as expected. When called from an architected set of namespaces, the byte offsets appear to move around. Is this expected?

Update:

Test Code:

eeprom.h:

```<code>#include <Wire.h>
#include <Arduino.h>

#ifndef EEPROM_H
#define EEPROM_H

struct ExampleStructure {
  const byte magic[4] = {192,43,67,181};
  byte settingsVersion[4] = {0, 0, 0, 1};
};

namespace EEPROM {

  const int memoryI2CAddress = 0x50;

  bool CompareArrays(byte *array1, byte *array2, unsigned int count) {
    bool result = true;
    for (unsigned int i = 0; i < count; i++) { result = result && (array1[i] == array2[i]); }
    return result;
  }

  void ReadBytes(byte *result, unsigned int count, unsigned int baseAddress) {

    while (Wire.available()) { Wire.read(); } //Clear buffer

    Wire.beginTransmission(memoryI2CAddress);
    Wire.write((byte)(baseAddress >> 8));
    Wire.write((byte)(baseAddress & 0xFF));
    Wire.endTransmission();

    unsigned int returnCount = Wire.requestFrom(memoryI2CAddress, count);
    for (unsigned int i = 0; i < returnCount; i++) { result[i] = Wire.read(); }
  }

  void WriteBytes(byte *values, unsigned int count, unsigned int address) {
    Wire.beginTransmission(memoryI2CAddress);
    Wire.write((byte)(address >> 8));
    Wire.write((byte)(address & 0xFF));
    Wire.write(values, count);
    Wire.endTransmission();

    delay(5);

    byte checkBytes[count];
    ReadBytes(checkBytes, count, address);
    if (!CompareArrays(values, checkBytes, count)) { Serial.println("Written bytes not written correctly."); }
    else { Serial.println("Everything went fine"); }
  }

  template <typename U>
  void StoreStruct(U *structure, unsigned int location) {
    byte values[sizeof(U)];
    memcpy(values, structure, sizeof(U));
    WriteBytes(values, sizeof(U), location);
  }

  void Initialise() {
    Wire.begin();
    ExampleStructure a;
    a.settingsVersion[0] = 0;
    a.settingsVersion[1] = 0;
    a.settingsVersion[2] = 0;
    a.settingsVersion[3] = 1;

    StoreStruct(&a, 896);
  }
}

#endif
</code>```

settings.h

```<code>#include "eeprom.h"

#ifndef SETTINGS_H
#define SETTINGS_H

namespace Settings {

  void Initialise() {

    ExampleStructure a;
    a.settingsVersion[0] = 0;
    a.settingsVersion[1] = 0;
    a.settingsVersion[2] = 0;
    a.settingsVersion[3] = 1;

    EEPROM::StoreStruct(&a, 896);
  }
}

#endif
</code>```

Main file:

```<code>#include "eeprom.h"
#include "settings.h"

void setup() {
  Serial.begin(115200);

  Settings::Initialise();
  EEPROM::Initialise();
}

void loop() {}
</code>```

Output:

```<code>Writing:
Written bytes not written correctly.
Writing:
Everything went fine
</code>```

答: The answer to this problem was obscure and entirely unrelated to structures and namespaces. Essentially I was using an uninitialised library. (Wire.h)</p>

Body:
I am looking to write a firmware that writes a structure to and reads it back from EEPROM memory. Converting the structure into a byte stream is working, however when I abstract the problem by putting the structure into a namespace, or call functions that pass pointers to the structure, the byte offsets seem to change by multiples of 2.

To create the memory map of the structure I am using the methods:

template <typename U>
void StoreStruct(U *structure, unsigned int location) {
  byte values[sizeof(U)];
  memcpy(values, structure, sizeof(U));
  ...
}

template <typename U>
void RetrieveStruct(U *result, unsigned int location) {
  byte readValues[sizeof(U)];
  ...
  memcpy(result, readValues, sizeof(U));
}

When calling these from a common namespace, they function as expected. When called from an architected set of namespaces, the byte offsets appear to move around. Is this expected?

Update:

Test Code:

eeprom.h:

#include <Wire.h>
#include <Arduino.h>

#ifndef EEPROM_H
#define EEPROM_H

struct ExampleStructure {
  const byte magic[4] = {192,43,67,181};
  byte settingsVersion[4] = {0, 0, 0, 1};
};

namespace EEPROM {

  const int memoryI2CAddress = 0x50;

  bool CompareArrays(byte *array1, byte *array2, unsigned int count) {
    bool result = true;
    for (unsigned int i = 0; i < count; i++) { result = result && (array1[i] == array2[i]); }
    return result;
  }

  void ReadBytes(byte *result, unsigned int count, unsigned int baseAddress) {

    while (Wire.available()) { Wire.read(); } //Clear buffer

    Wire.beginTransmission(memoryI2CAddress);
    Wire.write((byte)(baseAddress >> 8));
    Wire.write((byte)(baseAddress & 0xFF));
    Wire.endTransmission();

    unsigned int returnCount = Wire.requestFrom(memoryI2CAddress, count);
    for (unsigned int i = 0; i < returnCount; i++) { result[i] = Wire.read(); }
  }

  void WriteBytes(byte *values, unsigned int count, unsigned int address) {
    Wire.beginTransmission(memoryI2CAddress);
    Wire.write((byte)(address >> 8));
    Wire.write((byte)(address & 0xFF));
    Wire.write(values, count);
    Wire.endTransmission();

    delay(5);

    byte checkBytes[count];
    ReadBytes(checkBytes, count, address);
    if (!CompareArrays(values, checkBytes, count)) { Serial.println("Written bytes not written correctly."); }
    else { Serial.println("Everything went fine"); }
  }

  template <typename U>
  void StoreStruct(U *structure, unsigned int location) {
    byte values[sizeof(U)];
    memcpy(values, structure, sizeof(U));
    WriteBytes(values, sizeof(U), location);
  }

  void Initialise() {
    Wire.begin();
    ExampleStructure a;
    a.settingsVersion[0] = 0;
    a.settingsVersion[1] = 0;
    a.settingsVersion[2] = 0;
    a.settingsVersion[3] = 1;

    StoreStruct(&a, 896);
  }
}

#endif

settings.h

#include "eeprom.h"

#ifndef SETTINGS_H
#define SETTINGS_H

namespace Settings {

  void Initialise() {

    ExampleStructure a;
    a.settingsVersion[0] = 0;
    a.settingsVersion[1] = 0;
    a.settingsVersion[2] = 0;
    a.settingsVersion[3] = 1;

    EEPROM::StoreStruct(&a, 896);
  }
}

#endif

Main file:

#include "eeprom.h"
#include "settings.h"

void setup() {
  Serial.begin(115200);

  Settings::Initialise();
  EEPROM::Initialise();
}

void loop() {}

Output:

Writing:
Written bytes not written correctly.
Writing:
Everything went fine


问:
Simple substraction on PHP (Arithmetic Operators)
I need some help with this simple substraction:

```<code>$savings = ($newprice - $newvalue);
</code>```

$newprice and $newvalue are values like 120.00 and 40.00

The problem is that the result is shown as 80 , without the .00 (dot00) at the end.

I will like to keep the values on the same format (a dot plus double cero at the end); what I need to change or include to that code ?

Thanks in advance

答:
I think you need to do</p>

```<code>$savings = 80;
echo number_format($savings);
</code>```

Body:
I need some help with this simple substraction:

$savings = ($newprice - $newvalue);

$newprice and $newvalue are values like 120.00 and 40.00

The problem is that the result is shown as 80 , without the .00 (dot00) at the end.

I will like to keep the values on the same format (a dot plus double cero at the end); what I need to change or include to that code ?

Thanks in advance

Body:
I think you need to do

$savings = 80;
echo number_format($savings);


问:
For which reason this Angular Service is not working?
I created an Angular app with controller. I can successfully use the controller (with Postman, see screenshot below).

At the fronted I implemented a new component including service to show the data from controller (see code below). The service is not working. No data are shown at the application.

I made a breakpoint in feedback.service.ts/getFeedbacks() and in feedback.component.ts/ngOnInit(). Both are reached.

I mad a breakpoint at my controller and this one is never reached (except using postman).

Why doesn't the data from the controller reach the GUI?

feedback.component.html:

Feedback List:

       {{feedback.comment}}

Count: {{feedbacks.length}}

```
<p>feedback.component.ts:</p>
```import { Component, OnInit } from '@angular/core';
import { Feedback } from './feedback';
import { FeedbackService } from './feedback.service';

@Component({
  selector: 'app-feedback',
  templateUrl: './feedback.component.html',
  styleUrls: ['./feedback.component.css']
})
export class FeedbackComponent implements OnInit {
  feedbacks: Feedback[] = [];
    objects: any;

  constructor(private feedbackService: FeedbackService) { }

  ngOnInit(): void {
    this.feedbackService
      .getFeedbacks()
      .subscribe(feedbacks => this.feedbacks = feedbacks);
  }
}
```
<p>feedback.service.ts:</p>
```import { HttpClient } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { Observable } from 'rxjs';
import { Feedback } from './feedback';

@Injectable({
  providedIn: 'root'
})
export class FeedbackService {

  constructor(private http: HttpClient) { }

  getFeedbacks(): Observable<Feedback[]> {
    let result: Observable<Feedback[]>;
    result = this.http.get<Feedback[]>('/feedback');
    return result;
  }
}
```
<p>feedback.ts:</p>
```export interface Feedback {
    id:      number;
    comment: string;
    userId:  number;
}
```
<p>app.modules.ts:</p>
```// other imports ...
import { FeedbackComponent } from './feedback/feedback.component';
import { FeedbackService } from './feedback/feedback.service';

@NgModule({
  declarations: [
    AppComponent,
    NavMenuComponent,
    HomeComponent,
    FeedbackComponent
  ],
  imports: [
    BrowserModule.withServerTransition({ appId: 'ng-cli-universal' }),
    HttpClientModule,
    FormsModule,
    RouterModule.forRoot([
      { path: '', component: FeedbackComponent, pathMatch: 'full' }
    ]),
    BrowserAnimationsModule,
    MatToolbarModule
  ],
  providers: [FeedbackService],
  bootstrap: [AppComponent]
})
export class AppModule { }
```

Screenshot from browser:

答:
Configure so that Angular hits the correct url andport localhost:5235/feedback. Using developer tools and inspecting network tab you can find your GET request and have look if it's heading to the right direction. Easies way would be to use Angular's enviourment files and change the baseUrl.

https://stackoverflow.com/a/46532683/15439733

Then after that make sure CORS is enabled on your backend so Angular from another url localhost:44477 can access that endpoint.

https://www.freakyjolly.com/angular-proxy-configuration-to-handle-cors-issue/

Body:
I created an Angular app with controller. I can successfully use the controller (with Postman, see screenshot below).

At the fronted I implemented a new component including service to show the data from controller (see code below). The service is not working. No data are shown at the application.

I made a breakpoint in feedback.service.ts/getFeedbacks() and in feedback.component.ts/ngOnInit(). Both are reached.

I mad a breakpoint at my controller and this one is never reached (except using postman).

Why doesn't the data from the controller reach the GUI?

feedback.component.html:

Feedback List:

       {{feedback.comment}}

Count: {{feedbacks.length}}

feedback.component.ts:

import { Component, OnInit } from '@angular/core';
import { Feedback } from './feedback';
import { FeedbackService } from './feedback.service';

@Component({
  selector: 'app-feedback',
  templateUrl: './feedback.component.html',
  styleUrls: ['./feedback.component.css']
})
export class FeedbackComponent implements OnInit {
  feedbacks: Feedback[] = [];
    objects: any;

  constructor(private feedbackService: FeedbackService) { }

  ngOnInit(): void {
    this.feedbackService
      .getFeedbacks()
      .subscribe(feedbacks => this.feedbacks = feedbacks);
  }
}

feedback.service.ts:

import { HttpClient } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { Observable } from 'rxjs';
import { Feedback } from './feedback';

@Injectable({
  providedIn: 'root'
})
export class FeedbackService {

  constructor(private http: HttpClient) { }

  getFeedbacks(): Observable<Feedback[]> {
    let result: Observable<Feedback[]>;
    result = this.http.get<Feedback[]>('/feedback');
    return result;
  }
}

feedback.ts:

export interface Feedback {
    id:      number;
    comment: string;
    userId:  number;
}

app.modules.ts:

// other imports ...
import { FeedbackComponent } from './feedback/feedback.component';
import { FeedbackService } from './feedback/feedback.service';

@NgModule({
  declarations: [
    AppComponent,
    NavMenuComponent,
    HomeComponent,
    FeedbackComponent
  ],
  imports: [
    BrowserModule.withServerTransition({ appId: 'ng-cli-universal' }),
    HttpClientModule,
    FormsModule,
    RouterModule.forRoot([
      { path: '', component: FeedbackComponent, pathMatch: 'full' }
    ]),
    BrowserAnimationsModule,
    MatToolbarModule
  ],
  providers: [FeedbackService],
  bootstrap: [AppComponent]
})
export class AppModule { }

Screenshot from browser:


问:
Way to avoid nested ifelse statement in R
I have a dataframe that includes various ages and a value for each age. I would like to classify the different ages into broader age groups. To do so, I had to create a fairly complicated nested ifelse statement:

```<code>library(tidyverse)

df <- data.frame(age = c("15 to 17", "18 and 19", "20 to 24", "25 to 29", "30 to 34", "35 to 39", "40 to 44", "45 to 49", "50 to 54", "55 to 59"),
                 value = sample(1000:2000,10, replace=TRUE))

new_df = df %>%
  mutate(age_band =
           ifelse(age %in% c("15 to 17","18 and 19"), '15 to 19', ifelse(age %in% c("20 to 24","25 to 29"), '20s', ifelse(age %in% c("30 to 34","35 to 39"), '30s','40+'))))
</code>```

Is there any way to do this without using such complex nested statements? The data goes all the way to ages 85 and over, and it got very complicated to classify each different age group.

答:
What you can do is take the first two characters to get the first age number of your current group and then just use cut and re-define your breaks and  labels.

code

```<code>df %>%
  mutate(age_band = cut(
    as.numeric(substr(age, 1, 2)),
    breaks = c(15, 20, 30, 40, 100),
    labels = c("15 to 19", "20s", "30s", "40+"),
    right = F)
  )
</code>```

output

```<code>         age value  age_band
1   15 to 17  1216  15 to 19
2  18 and 19  1983  15 to 19
3   20 to 24  1839       20s
4   25 to 29  1558       20s
5   30 to 34  1741       30s
6   35 to 39  1171       30s
7   40 to 44  1324       40+
8   45 to 49  1354       40+
9   50 to 54  1342       40+
10  55 to 59  1467       40+
</code>```

Body:
I have a dataframe that includes various ages and a value for each age. I would like to classify the different ages into broader age groups. To do so, I had to create a fairly complicated nested ifelse statement:

library(tidyverse)

df <- data.frame(age = c("15 to 17", "18 and 19", "20 to 24", "25 to 29", "30 to 34", "35 to 39", "40 to 44", "45 to 49", "50 to 54", "55 to 59"),
                 value = sample(1000:2000,10, replace=TRUE))

new_df = df %>%
  mutate(age_band =
           ifelse(age %in% c("15 to 17","18 and 19"), '15 to 19', ifelse(age %in% c("20 to 24","25 to 29"), '20s', ifelse(age %in% c("30 to 34","35 to 39"), '30s','40+'))))

Is there any way to do this without using such complex nested statements? The data goes all the way to ages 85 and over, and it got very complicated to classify each different age group.

Body:
What you can do is take the first two characters to get the first age number of your current group and then just use cut and re-define your breaks and  labels.

code

df %>%
  mutate(age_band = cut(
    as.numeric(substr(age, 1, 2)),
    breaks = c(15, 20, 30, 40, 100),
    labels = c("15 to 19", "20s", "30s", "40+"),
    right = F)
  )

output

         age value  age_band
1   15 to 17  1216  15 to 19
2  18 and 19  1983  15 to 19
3   20 to 24  1839       20s
4   25 to 29  1558       20s
5   30 to 34  1741       30s
6   35 to 39  1171       30s
7   40 to 44  1324       40+
8   45 to 49  1354       40+
9   50 to 54  1342       40+
10  55 to 59  1467       40+


问:
Using the OR operator (|) in jsonpath-ng python
I have a json structure (client_json) that looks like:

```<code>client_json = { "data": [ { "attributes": { "creators": [ { "name": "This is a person", "nameType": "Personal", "givenName": "the", "familyName": "person" }, { "name": "This is an organization", "nameType": "Organizational", "givenName": "the", "familyName": "organization" } ] } } ] }
</code>```

I am trying to use jsonpath-ng 1.4.3 (https://github.com/h2non/jsonpath-ng) to retrieve creator names.

```<code>from jsonpath_ng import jsonpath
from jsonpath_ng.ext import parse
</code>```

These two expressions give the expected results:

```<code>[match.value['name'] for match in parse("data[*].attributes.creators[?(@.nameType='Personal')]").find(client_json)]
[match.value['name'] for match in parse("data[*].attributes.creators[?(@.nameType='Organizational')]").find(client_json)]
</code>```

I am trying to combine them with an or operator and all of these expressions yield parse errors:

```<code>parse("data[*].attributes.creators[?(@.nameType == 'Organizational' | @.nameType == 'Personal')]")
parse("data[*].attributes.creators[?(@.nameType == 'Organizational' || @.nameType == 'Personal')]")
parse("data[*].attributes.creators[?(@.nameType == 'Organizational'), ?(@.nameType == 'Personal')]")
parse("data[*].attributes.creators[?(@.nameType == 'Organizational') || ?(@.nameType == 'Personal')]")
parse("data[*].attributes.creators[?(@.nameType == 'Organizational') | ?(@.nameType == 'Personal')]")
parse("data[*].attributes.creators[?(@.nameType = 'Organizational' | @.nameType = 'Personal')]")
</code>```

Thanks for the help.

答:
I bumped into this same problem. I got success using the regex option. Your expression would then become:

parse("data[*].attributes.creators[?(@.nameType =~ 'Organizational|Personal')]")

Body:
I have a json structure (client_json) that looks like:

client_json = { "data": [ { "attributes": { "creators": [ { "name": "This is a person", "nameType": "Personal", "givenName": "the", "familyName": "person" }, { "name": "This is an organization", "nameType": "Organizational", "givenName": "the", "familyName": "organization" } ] } } ] }

I am trying to use jsonpath-ng 1.4.3 (https://github.com/h2non/jsonpath-ng) to retrieve creator names.

from jsonpath_ng import jsonpath
from jsonpath_ng.ext import parse

These two expressions give the expected results:

[match.value['name'] for match in parse("data[*].attributes.creators[?(@.nameType='Personal')]").find(client_json)]
[match.value['name'] for match in parse("data[*].attributes.creators[?(@.nameType='Organizational')]").find(client_json)]

I am trying to combine them with an or operator and all of these expressions yield parse errors:

parse("data[*].attributes.creators[?(@.nameType == 'Organizational' | @.nameType == 'Personal')]")
parse("data[*].attributes.creators[?(@.nameType == 'Organizational' || @.nameType == 'Personal')]")
parse("data[*].attributes.creators[?(@.nameType == 'Organizational'), ?(@.nameType == 'Personal')]")
parse("data[*].attributes.creators[?(@.nameType == 'Organizational') || ?(@.nameType == 'Personal')]")
parse("data[*].attributes.creators[?(@.nameType == 'Organizational') | ?(@.nameType == 'Personal')]")
parse("data[*].attributes.creators[?(@.nameType = 'Organizational' | @.nameType = 'Personal')]")

Thanks for the help.


问:
How to fetch @value from following json
I have following json.I want to fetch "rdfs:label"'s value when  "@type" is  "T:Class".

I want output like
Stand1
Stand2

How to achieved this.

I have tried like this.

string json = File.ReadAllText("Filepath");
JObject Search = JObject.Parse(json);

IList results = Search["@standard"][0].Children().ToList();
foreach (JToken result in results)
{
}
It gives me entire inner @standard block.

```<code>{
  "@School": {
    "name": "Vikas Mandir",
    "subject": "Maths",
    "author": "Joshi",

  },
  "@standard": [
    {
      "@id": "vikas:Stand1",

      "@standard": [

        {
          "@id": "vikas:Stand12",
          "@type": "T:Class",
          "tag:Std:label": {
            "@value": "Stand1"
          },
          "rdfs:label": {
            "@value": "Stand1"
          }
        },

        {
          "@id": "vikas:Stand123",
          "@type": "T:Class",
          "tag:Std:label": {
            "@value": "Stand2"
          },
          "rdfs:label": {
            "@value": "Stand2"
          }
        }
]
}
]
}
</code>```

答:
try this

```<code>    var prop = new List<JToken>();

    GetObject(jsonParsed, prop, "rdfs:label", null, true);
    List<string> found = prop.Where(i => (string)i["@type"] == "T:Class")
    .Select(i => (string) ((JObject)i).Properties().First(x => x.Name == "rdfs:label").Value["@value"]).ToList();

    Console.WriteLine(string.Join(",",found)); //Stand1,Stand2
</code>```

helper

```<code>public void GetObject(JToken obj, List<JToken> result, string name = null, string value = null, bool getParent = false)
{
    if (obj.GetType().Name == "JObject")
        foreach (var property in ((JObject)obj).Properties())
        {
            if (property.Value.GetType().Name == "JValue"
                && (name == null || (string)property.Name == name)
                && (value == null || (string)property.Value == value))
            {
                if (getParent) result.Add(property.Parent); else result.Add(property);
            }
            else if (property.Value.GetType().Name == "JObject")
            {
                if (name != null && (string)property.Name == name) result.Add(property.Parent);
                GetObject(property.Value, result, name, value);
            }
            else if (property.Value.GetType().Name == "JArray") GetObject(property.Value, result, name, value);
        }
    if (obj.GetType().Name == "JArray")
    {
        foreach (var property in ((JArray)obj))
        {
            if (property.GetType().Name == "JObject") GetObject(property, result, name, value);
            if (property.GetType().Name == "JArray") GetObject(property, result, name, value);
            if (property.GetType().Name == "JValue"
                 && (value == null || (string)property == value))
            {
                if (getParent) result.Add((JArray)obj); else result.Add(property);
            }
        }
    }
}
</code>```

Title: How to fetch @value from following json

Body:
I have following json.I want to fetch "rdfs:label"'s value when  "@type" is  "T:Class".

I want output like
Stand1
Stand2

How to achieved this.

I have tried like this.

string json = File.ReadAllText("Filepath");
JObject Search = JObject.Parse(json);

IList results = Search["@standard"][0].Children().ToList();
foreach (JToken result in results)
{
}
It gives me entire inner @standard block.

{
  "@School": {
    "name": "Vikas Mandir",
    "subject": "Maths",
    "author": "Joshi",

  },
  "@standard": [
    {
      "@id": "vikas:Stand1",

      "@standard": [

        {
          "@id": "vikas:Stand12",
          "@type": "T:Class",
          "tag:Std:label": {
            "@value": "Stand1"
          },
          "rdfs:label": {
            "@value": "Stand1"
          }
        },

        {
          "@id": "vikas:Stand123",
          "@type": "T:Class",
          "tag:Std:label": {
            "@value": "Stand2"
          },
          "rdfs:label": {
            "@value": "Stand2"
          }
        }
]
}
]
}

Body:
try this

    var prop = new List<JToken>();

    GetObject(jsonParsed, prop, "rdfs:label", null, true);
    List<string> found = prop.Where(i => (string)i["@type"] == "T:Class")
    .Select(i => (string) ((JObject)i).Properties().First(x => x.Name == "rdfs:label").Value["@value"]).ToList();

    Console.WriteLine(string.Join(",",found)); //Stand1,Stand2

helper

public void GetObject(JToken obj, List<JToken> result, string name = null, string value = null, bool getParent = false)
{
    if (obj.GetType().Name == "JObject")
        foreach (var property in ((JObject)obj).Properties())
        {
            if (property.Value.GetType().Name == "JValue"
                && (name == null || (string)property.Name == name)
                && (value == null || (string)property.Value == value))
            {
                if (getParent) result.Add(property.Parent); else result.Add(property);
            }
            else if (property.Value.GetType().Name == "JObject")
            {
                if (name != null && (string)property.Name == name) result.Add(property.Parent);
                GetObject(property.Value, result, name, value);
            }
            else if (property.Value.GetType().Name == "JArray") GetObject(property.Value, result, name, value);
        }
    if (obj.GetType().Name == "JArray")
    {
        foreach (var property in ((JArray)obj))
        {
            if (property.GetType().Name == "JObject") GetObject(property, result, name, value);
            if (property.GetType().Name == "JArray") GetObject(property, result, name, value);
            if (property.GetType().Name == "JValue"
                 && (value == null || (string)property == value))
            {
                if (getParent) result.Add((JArray)obj); else result.Add(property);
            }
        }
    }
}


答:
You can filter those todos first then render later

```<code>todos.filter(todo => todo.status === 1).map(todo => (
    <p>{todo.title}</p>
))

todos.filter(todo => todo.status === 2).map(todo => (
    <p>{todo.title}</p>
))

todos.filter(todo => todo.status === 3).map(todo => (
    <p>{todo.title}</p>
))
</code>```

or create a reuseable function to render those todos

```<code>function renderTodoWithStatus(todos, status) {
    return todos.filter(todo => todo.status === status).map(todo => (
        <p>{todo.title}</p>
    ))
}
</code>```

Title: multiple conditional renderings inside a map function

Body:
Hi there I'm looking if there's a better way to render my todos

I have this

         {
            todos.map((todo) => (

                todo.status === 1 && (

{todo.title}

                )
            ))
        }
        {
            todos.map((todo) => (
                todo.status === 2 && (

{todo.title}

                )
            ))
        }
        {
            todos.map((todo) => (
                todo.status === 3 && (

{todo.title}

                )
            ))
        }

Is there a way to do this?

Thanks a lot

Body:
You can filter those todos first then render later

todos.filter(todo => todo.status === 1).map(todo => (
    <p>{todo.title}</p>
))

todos.filter(todo => todo.status === 2).map(todo => (
    <p>{todo.title}</p>
))

todos.filter(todo => todo.status === 3).map(todo => (
    <p>{todo.title}</p>
))

or create a reuseable function to render those todos

function renderTodoWithStatus(todos, status) {
    return todos.filter(todo => todo.status === status).map(todo => (
        <p>{todo.title}</p>
    ))
}


问:
getDigitalGoodsService("https://play.google.com/billing") always returning “DOMException: unsupported context” error
I have a working TWA on Play Store  (website reference) that I’m trying to update for enabling it to handle google play digital goods payments. I’ve already implemented an in-app purchase using stripe. When I submitted a simple update to the app play store images it got rejected because they noticed the missing google in-app purchase that I didn’t know yet that was required. So I’m working now on implementing it.

What I’ve made:

Updated my twa-manifest.json to include billing permissions. As the first step on this article by google:

```<code>  ...
  "enableNotifications": true,
  "features": {
    "playBilling": {
      "enabled": true
    }
  },
  "alphaDependencies": {
    "enabled": true
  },
  ...
</code>```

As I use Android Studio and not Bubblewrapp to build my app, I went to this other tutorial article And followed every step in it: (a) update build gradle, sync it. (b) Create DelegationService.java and reference it on AndroidManifest.xml (c) Added the service and the activity recommended by them, also to AndroidManifest.xml.

I made the app signed bundle release build  and for quick testing, I’ve uploaded it to the play store internal testing

The problem:

I’ve used this generated testing link to download and install the new release on two devices: a Pixel 2 (Api 30) Emulator, and a  Redmi Note 8 and as my target is to implement the play store digital goods api, I inspected the app from chrome://inspect/#devices and noticed that getDigitalGoodsService is enabled but fails when getting the Google Play Billing service:

```<code>if('getDigitalGoodsService' in window) {
    const service = await getDigitalGoodsService("https://play.google.com/billing")
}
</code>```

Which the getDigitalGoodsService fails with the error:

```<code>Uncaught (in promise) DOMException: unsupported context
</code>```

My hypothesis is that it isn’t working because the app is download from a testing link and not as a Play Store approved release.

Also, the URL bar is showing. But again my hypothesis to it is the same as above because I’ve made 0 changes to the digital asset links configuration that in the current production release is working fine on users' devices. But I wonder if this fact should give some explanation on why the getDigitalGoodsService fails.

Anyway, I hope I’m wrong on my hypothesis because it would mean that first I would need to release a version with the billing permissions which would be rejected because they will not see the implementation of google play billing, which is required to in-app purchases implementations. So as I don’t have an approved TWA release to debug and implement the billing, I would be stuck on the process. Unless of course, I’ve not yet noticed another way to solve it.

Any suggestions?

答:
I've found the solution. The problem is that my Digital Asset Links configuration wasn't correctly configured. The point I was missing is that each apk/aab release might have its own sha256 fingerprint when you are testing locally or from a play store internal testing download link.

I discovered it on this doc. In the end of it they recommend this app: Asset Links Tool from Play Store.

For those who might come here in the future, remember to, using this Asset Links app, find and take your app configuration, and append it to your production assetlinks.json (on example.com/.well-known/assetlinks.json):

```<code>[
// ...your previous configuration
  {
    "relation": ["delegate_permission/common.handle_all_urls"],
    "target": {
      // your current testing asset links fingerprint took from the Asset Links app
    }
  }
]
</code>```

Body:
I have a working TWA on Play Store  (website reference) that I’m trying to update for enabling it to handle google play digital goods payments. I’ve already implemented an in-app purchase using stripe. When I submitted a simple update to the app play store images it got rejected because they noticed the missing google in-app purchase that I didn’t know yet that was required. So I’m working now on implementing it.

What I’ve made:

Updated my twa-manifest.json to include billing permissions. As the first step on this article by google:

  ...
  "enableNotifications": true,
  "features": {
    "playBilling": {
      "enabled": true
    }
  },
  "alphaDependencies": {
    "enabled": true
  },
  ...

As I use Android Studio and not Bubblewrapp to build my app, I went to this other tutorial article And followed every step in it: (a) update build gradle, sync it. (b) Create DelegationService.java and reference it on AndroidManifest.xml (c) Added the service and the activity recommended by them, also to AndroidManifest.xml.

I made the app signed bundle release build  and for quick testing, I’ve uploaded it to the play store internal testing

The problem:

I’ve used this generated testing link to download and install the new release on two devices: a Pixel 2 (Api 30) Emulator, and a  Redmi Note 8 and as my target is to implement the play store digital goods api, I inspected the app from chrome://inspect/#devices and noticed that getDigitalGoodsService is enabled but fails when getting the Google Play Billing service:

if('getDigitalGoodsService' in window) {
    const service = await getDigitalGoodsService("https://play.google.com/billing")
}

Which the getDigitalGoodsService fails with the error:

Uncaught (in promise) DOMException: unsupported context

My hypothesis is that it isn’t working because the app is download from a testing link and not as a Play Store approved release.

Also, the URL bar is showing. But again my hypothesis to it is the same as above because I’ve made 0 changes to the digital asset links configuration that in the current production release is working fine on users' devices. But I wonder if this fact should give some explanation on why the getDigitalGoodsService fails.

Anyway, I hope I’m wrong on my hypothesis because it would mean that first I would need to release a version with the billing permissions which would be rejected because they will not see the implementation of google play billing, which is required to in-app purchases implementations. So as I don’t have an approved TWA release to debug and implement the billing, I would be stuck on the process. Unless of course, I’ve not yet noticed another way to solve it.

Any suggestions?

Body:
I've found the solution. The problem is that my Digital Asset Links configuration wasn't correctly configured. The point I was missing is that each apk/aab release might have its own sha256 fingerprint when you are testing locally or from a play store internal testing download link.

I discovered it on this doc. In the end of it they recommend this app: Asset Links Tool from Play Store.

For those who might come here in the future, remember to, using this Asset Links app, find and take your app configuration, and append it to your production assetlinks.json (on example.com/.well-known/assetlinks.json):

[
// ...your previous configuration
  {
    "relation": ["delegate_permission/common.handle_all_urls"],
    "target": {
      // your current testing asset links fingerprint took from the Asset Links app
    }
  }
]


问:
Frequently repeated try/except in Python
Firstly, I'm not sure if my approach is proper, so I'm open to a variety of suggestions.

If try/except statements are frequently repeated in code, are there any good ways to shorten them or avoid fully writing them out?

```<code>try:
    # Do similar thing
    os.remove('/my/file')
except OSError, e:
    # Same exception handing
    pass

try:
    # Do similar thing
    os.chmod('/other/file', 0700)
except OSError, e:
    #Same exception handling
    pass
</code>```

For example, for one line actions you could define a exception handling wrapper and then pass a lambda function:

```<code>def may_exist(func):
    "Work with file which you are not sure if exists."""
    try:
        func()
    except OSError, e:
        # Same exception handling
        pass

may_exist(lambda: os.remove('/my/file'))
may_exist(lambda: os.chmod('/other/file', 0700))
</code>```

Does this 'solution' just make things less clear? Should I just fully write out all the try/except statements?

答:
The best way to abstract exception handling is with a context manager:

```<code>from contextlib import contextmanager
@contextmanager
def common_handling():
    try:
        yield
    finally:
        # whatever your common handling is
</code>```

then:

```<code>with common_handling():
    os.remove('/my/file')

with common_handling():
    os.chmod('/other/file', 0700)
</code>```

This has the advantage that you can put full statements, and more than one of them, in each common_handling block.

Keep in mind though, your need to use the same handling over and over again feels a lot like over-handling exceptions.  Are you sure you need to do this much?

Body:
Firstly, I'm not sure if my approach is proper, so I'm open to a variety of suggestions.

If try/except statements are frequently repeated in code, are there any good ways to shorten them or avoid fully writing them out?

try:
    # Do similar thing
    os.remove('/my/file')
except OSError, e:
    # Same exception handing
    pass

try:
    # Do similar thing
    os.chmod('/other/file', 0700)
except OSError, e:
    #Same exception handling
    pass

For example, for one line actions you could define a exception handling wrapper and then pass a lambda function:

def may_exist(func):
    "Work with file which you are not sure if exists."""
    try:
        func()
    except OSError, e:
        # Same exception handling
        pass

may_exist(lambda: os.remove('/my/file'))
may_exist(lambda: os.chmod('/other/file', 0700))

Does this 'solution' just make things less clear? Should I just fully write out all the try/except statements?

Body:
The best way to abstract exception handling is with a context manager:

from contextlib import contextmanager
@contextmanager
def common_handling():
    try:
        yield
    finally:
        # whatever your common handling is

then:

with common_handling():
    os.remove('/my/file')

with common_handling():
    os.chmod('/other/file', 0700)

This has the advantage that you can put full statements, and more than one of them, in each common_handling block.

Keep in mind though, your need to use the same handling over and over again feels a lot like over-handling exceptions.  Are you sure you need to do this much?


问:
C++ variadic template function parameter with default value
I have a function which takes one parameter with a default value. Now I also want it to take a variable number of parameters and forward them to some other function. Function parameters with default value have to be last, so... can I put that parameter after the variadic pack and the compiler will detect whether I'm supplying it or not when calling the function?

(Assuming the pack doesn't contain the type of that one last parameter. If necessary, we can assume that, because that type is generally not supposed to be known to the user, otherwise it's considered as wrong usage of my interface anyway....)

```<code>template <class... Args>
void func (Args&&... args, SomeSpecialType num = fromNum(5))
{
}
</code>```

答:
Since C++17 there is way to work around this limitation, by using class template argument deduction and user-defined deduction guides.

This is espactialy useful for C++20 std::source_location.

Here is C++17 demo:

#include <iostream>

int defaultValueGenerator()
{
    static int c = 0;
    return ++c;
}

template <typename... Ts>
struct debug
{
    debug(Ts&&... ts, int c = defaultValueGenerator())
    {
        std::cout << c << " : ";
        ((std::cout << std::forward<Ts>(ts) << " "), ...);
        std::cout << std::endl;
    }
};

template <typename... Ts>
debug(Ts&&...args) -> debug<Ts...>;

void test()
{
    debug();
    debug(9);
    debug<>(9);
}

int main()
{
    debug(5, 'A', 3.14f, "foo");
    test();
    debug("bar", 123, 2.72);
}
```

Live demo

Demo with source_location (should be available since C++20, but still for compilers it is experimental).

Body:
I have a function which takes one parameter with a default value. Now I also want it to take a variable number of parameters and forward them to some other function. Function parameters with default value have to be last, so... can I put that parameter after the variadic pack and the compiler will detect whether I'm supplying it or not when calling the function?

(Assuming the pack doesn't contain the type of that one last parameter. If necessary, we can assume that, because that type is generally not supposed to be known to the user, otherwise it's considered as wrong usage of my interface anyway....)

template <class... Args>
void func (Args&&... args, SomeSpecialType num = fromNum(5))
{
}

Body:
Since C++17 there is way to work around this limitation, by using class template argument deduction and user-defined deduction guides.

This is espactialy useful for C++20 std::source_location.

Here is C++17 demo:

#include <iostream>

int defaultValueGenerator()
{
    static int c = 0;
    return ++c;
}

template <typename... Ts>
struct debug
{
    debug(Ts&&... ts, int c = defaultValueGenerator())
    {
        std::cout << c << " : ";
        ((std::cout << std::forward<Ts>(ts) << " "), ...);
        std::cout << std::endl;
    }
};

template <typename... Ts>
debug(Ts&&...args) -> debug<Ts...>;

void test()
{
    debug();
    debug(9);
    debug<>(9);
}

int main()
{
    debug(5, 'A', 3.14f, "foo");
    test();
    debug("bar", 123, 2.72);
}

Live demo

Demo with source_location (should be available since C++20, but still for compilers it is experimental).


问:
Activity indicator not showing in pagination for tableview in Swift
I am using pagination for tableview, for that I have created spinner for tableview footer and calling that in scrollViewDidEndDragging but the spinner is not showing.. while pagination

code: with this code pagination is working but createSpinnerFooter is calling but not showing, why? where am i wrong. please guide me

```<code> var currentPageNumberVM: Int = 1
 private func createSpinnerFooter() -> UIView {

    let footerView = UIView(frame: CGRect(x: 0, y: 0, width: view.frame.size.width, height: 100))

    let spinner = UIActivityIndicatorView()
    spinner.center = footerView.center
    footerView.addSubview(spinner)
    spinner.startAnimating()
    return footerView
   }

   //and calling here
   func scrollViewDidEndDragging(_ scrollView: UIScrollView, willDecelerate decelerate: Bool) {

     //Bottom Refresh
     if scrollView == resultTableView{

        if (((scrollView.contentOffset.y + scrollView.frame.size.height) >= scrollView.contentSize.height))
        //if scrollView.contentOffset.y > (resultTableView.contentSize.height-100-scrollView.frame.size.height)
        {
            resultTableView.tableFooterView = createSpinnerFooter()
            print("refresh called")
            self.refresh()
        }
    }
    }

   @objc func refresh() {
    if currentPageNumberVM <= searchData?.result?.jobs?.last_page ?? 1 {
        jobSearchResultServiceCall()//service call

    } else {
        self.view.makeToast("No more data to show")
    resultTableView.tableFooterView = nil

    }
   }
</code>```

Edit: if i move resultTableView.tableFooterView = nil to else then issue is createSpinnerFooter is showing but once its load then cells not reloading i mean pagination is not working until i scroll again, why? where is the issue.

答:
It's because of resultTableView.tableFooterView = nil in your refresh() function that causes the spinner to be removed as soon as it was added.

Here is how

First you add the spinner in scrollViewDidEndDragging with this line of code resultTableView.tableFooterView = createSpinnerFooter()

Then you call self.refresh() immediately which I believe calls an API in the background

However, in refresh you are also nil the footer view before the API call has completed resultTableView.tableFooterView = nil

All this happens so fast that you don't see the spinner being added and removed.

This line resultTableView.tableFooterView = nil should go in your else case and it should go in your API completion handler after the API has returned with a response or error

Update

You need to move resultTableView.tableFooterView = nil to two places.

One is in else block - OK, you have done this.

Another one is in the completion handler of your API call. It seems like your API call does not handle completion so I recommend you have a look at resource 1 and resource 2 to understand how to set up a completion handler for your API call.

Completion handler will let you know when you api call has completed and this is the second place you need to make the spinner to nil.

You need to change your jobSearchResultServiceCall() to have a completion handler using the links above.

Once this is done, you will have code that looks like this

```<code>@objc func refresh() {

    if currentPageNumberVM <= searchData?.result?.jobs?.last_page ?? 1 {

        jobSearchResultServiceCall { [weak self] _ in
            // your API call has finished and here is the second place
            // to remove the spinner
            self?.resultTableView.tableFooterView = nil
        })

    } else {
        self.view.makeToast("No more data to show")
        resultTableView.tableFooterView = nil
    }
}
</code>```

Now your spinner gets dismissed if api call has completed or there are no more results to show

Body:
I am using pagination for tableview, for that I have created spinner for tableview footer and calling that in scrollViewDidEndDragging but the spinner is not showing.. while pagination

code: with this code pagination is working but createSpinnerFooter is calling but not showing, why? where am i wrong. please guide me

 var currentPageNumberVM: Int = 1
 private func createSpinnerFooter() -> UIView {

    let footerView = UIView(frame: CGRect(x: 0, y: 0, width: view.frame.size.width, height: 100))

    let spinner = UIActivityIndicatorView()
    spinner.center = footerView.center
    footerView.addSubview(spinner)
    spinner.startAnimating()
    return footerView
   }

   //and calling here
   func scrollViewDidEndDragging(_ scrollView: UIScrollView, willDecelerate decelerate: Bool) {

     //Bottom Refresh
     if scrollView == resultTableView{

        if (((scrollView.contentOffset.y + scrollView.frame.size.height) >= scrollView.contentSize.height))
        //if scrollView.contentOffset.y > (resultTableView.contentSize.height-100-scrollView.frame.size.height)
        {
            resultTableView.tableFooterView = createSpinnerFooter()
            print("refresh called")
            self.refresh()
        }
    }
    }

   @objc func refresh() {
    if currentPageNumberVM <= searchData?.result?.jobs?.last_page ?? 1 {
        jobSearchResultServiceCall()//service call

    } else {
        self.view.makeToast("No more data to show")
    resultTableView.tableFooterView = nil

    }
   }

Edit: if i move resultTableView.tableFooterView = nil to else then issue is createSpinnerFooter is showing but once its load then cells not reloading i mean pagination is not working until i scroll again, why? where is the issue.

Body:
It's because of resultTableView.tableFooterView = nil in your refresh() function that causes the spinner to be removed as soon as it was added.

Here is how

First you add the spinner in scrollViewDidEndDragging with this line of code resultTableView.tableFooterView = createSpinnerFooter()

Then you call self.refresh() immediately which I believe calls an API in the background

However, in refresh you are also nil the footer view before the API call has completed resultTableView.tableFooterView = nil

All this happens so fast that you don't see the spinner being added and removed.

This line resultTableView.tableFooterView = nil should go in your else case and it should go in your API completion handler after the API has returned with a response or error

Update

You need to move resultTableView.tableFooterView = nil to two places.

One is in else block - OK, you have done this.

Another one is in the completion handler of your API call. It seems like your API call does not handle completion so I recommend you have a look at resource 1 and resource 2 to understand how to set up a completion handler for your API call.

Completion handler will let you know when you api call has completed and this is the second place you need to make the spinner to nil.

You need to change your jobSearchResultServiceCall() to have a completion handler using the links above.

Once this is done, you will have code that looks like this

@objc func refresh() {

    if currentPageNumberVM <= searchData?.result?.jobs?.last_page ?? 1 {

        jobSearchResultServiceCall { [weak self] _ in
            // your API call has finished and here is the second place
            // to remove the spinner
            self?.resultTableView.tableFooterView = nil
        })

    } else {
        self.view.makeToast("No more data to show")
        resultTableView.tableFooterView = nil
    }
}

Now your spinner gets dismissed if api call has completed or there are no more results to show