问:
things I don't get in python. bounded method acting like an alien
I don't understang this behaviour, I changed 'r' on the class 'f' and it is reflected back
on 'q' as you can see 'q.r' indicates that it is now referencing a 'lambda' function but at the same time the adress is always '0x037591F0' so why 'q.r()' is failling?</p>

```<code>class f:
    def r(self):
        print('bla bla bla')

>>> q=f()
>>> f.r
<function f.r at 0x0378F4B0>
>>> q.r
<bound method f.r of <__main__.f object at 0x037591F0>>
>>> f.r=lambda : 'google'
>>> f.r
<function <lambda> at 0x015F9348>
>>> q.r
<bound method <lambda> of <__main__.f object at 0x037591F0>>
>>> q.r()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: <lambda>() takes 0 positional arguments but 1 was given
</code>```

答:
First you need to understand what is an instance method and how it works,
remember in Python the instance methods lives in the class not in the object for that reason Python pass the self parameter in implicit way in every instance method (to know what object is calling the method).

In your example the lambda function does not receive any parameters and you dont use the self parameter, so that tell us that the method must be a static method(unbound method) not an instance method(bounded method), in other words that "r" method need to be bound to the class and not to the object.

```<code>class f:
    @staticmethod
    def r():
        print('bla bla bla')
</code>```

If stills confusing you read about the class methods, static methods and instance methods.

Body:
I don't understang this behaviour, I changed 'r' on the class 'f' and it is reflected back
on 'q' as you can see 'q.r' indicates that it is now referencing a 'lambda' function but at the same time the adress is always '0x037591F0' so why 'q.r()' is failling?

class f:
    def r(self):
        print('bla bla bla')

>>> q=f()
>>> f.r
<function f.r at 0x0378F4B0>
>>> q.r
<bound method f.r of <__main__.f object at 0x037591F0>>
>>> f.r=lambda : 'google'
>>> f.r
<function <lambda> at 0x015F9348>
>>> q.r
<bound method <lambda> of <__main__.f object at 0x037591F0>>
>>> q.r()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: <lambda>() takes 0 positional arguments but 1 was given

Body:
First you need to understand what is an instance method and how it works,
remember in Python the instance methods lives in the class not in the object for that reason Python pass the self parameter in implicit way in every instance method (to know what object is calling the method).

In your example the lambda function does not receive any parameters and you dont use the self parameter, so that tell us that the method must be a static method(unbound method) not an instance method(bounded method), in other words that "r" method need to be bound to the class and not to the object.

class f:
    @staticmethod
    def r():
        print('bla bla bla')

If stills confusing you read about the class methods, static methods and instance methods.


来源: stackexchange

问:
createdAt cannot be an array or an object
Can someone help me I'm having problems inserting a record in the database with sequelize, created_at and updated_at are automatically filled and this is with this error:

```<code>"name": "SequelizeValidationError",
"errors": [
    {
        "message": "createdAt cannot be an array or an object",
        "type": "string violation",
        "path": "createdAt",
        "value": "2020-05-28T22:04:45.023Z",
        "origin": "CORE",
        "instance": {
            "id": null,
            "placeId": "1",
            "userId": 3,
            "name": "Alex Santos",
            "email": "customer@gmail.com",
            "documento": "00000000000",
            "phone": "(37)98596-9869",
            "updatedAt": "2020-05-28T22:04:45.023Z",
            "createdAt": "2020-05-28T22:04:45.023Z"
        },
        "validatorKey": "not_a_string",
        "validatorName": null,
        "validatorArgs": []
    },
    {
        "message": "customer.updateAt cannot be null",
        "type": "notNull Violation",
        "path": "updateAt",
        "value": null,
        "origin": "CORE",
        "instance": {
            "id": null,
            "placeId": "1",
            "userId": 3,
            "name": "Alex Santos",
            "email": "customer@gmail.com",
            "documento": "031.682.546-81",
            "phone": "(37)98596-9869",
            "updatedAt": "2020-05-28T22:04:45.023Z",
            "createdAt": "2020-05-28T22:04:45.023Z"
        },
        "validatorKey": "is_null",
        "validatorName": null,
        "validatorArgs": []
    }
]
</code>```

}

Can someone provide any suggestions to help? I think in customer.js create() function is having some sort of miss from my side.

Could there be any other solution?

customer.js

```<code>   /* jshint indent: 1 */

module.exports = function(sequelize, DataTypes) {
    return sequelize.define('customer', {
        id: {
            type: DataTypes.INTEGER(11),
            allowNull: false,
            primaryKey: true,
            autoIncrement: true,
            field: 'id'
        },
        placeId: {
            type: DataTypes.INTEGER(11),
            allowNull: false,
            references: {
                model: 'places',
                key: 'id'
            },
            field: 'place_id'
        },
        userId: {
            type: DataTypes.INTEGER(11),
            allowNull: false,
            references: {
                model: 'users',
                key: 'id'
            },
            field: 'user_id'
        },
        customerId: {
            type: DataTypes.INTEGER(11),
            allowNull: true,
            field: 'customer_id'
        },
        name: {
            type: DataTypes.STRING(100),
            allowNull: false,
            field: 'name'
        },
        email: {
            type: DataTypes.STRING(255),
            allowNull: false,
            field: 'email'
        },
        documento: {
            type: DataTypes.STRING(16),
            allowNull: false,
            defaultValue: '',
            field: 'documento'
        },
        phone: {
            type: DataTypes.STRING(12),
            allowNull: false,
            field: 'phone'
        },
        createdAt: {
            type: DataTypes.STRING(255),
            allowNull: false,
            field: 'created_at'
        },
        updateAt: {
            type: DataTypes.STRING(255),
            allowNull: false,
            field: 'update_at'
        }

    }, {
        tableName: 'customer'
    });
};
</code>```

CustomerController.js

```<code>const Customers = require('./../models/custumers')
const Sequelize = require('sequelize');
const db = require('../../bin/database');
const Customer = new Customers(db, Sequelize);
exports.create = async(req, res) => {
    decodeToken = await jwt.decodeToken(req.headers['x-access-token'])
    let userId = decodeToken.id
    console.log(new Date())
    let { placeId, customerId, name, email, documento, phone } = req.body
    Customer.create({
            placeId,
            userId,
            customerId,
            name,
            email,
            documento,
            phone
        })
        .then((Customer) => {
            return res.status(200).send({ Customer: Customer })
        }).catch(err => {
            res.status(423).send(err);
        });
}
</code>```

答:
The error message is telling you what is wrong. You defined the createdAt column as a String but it would appear that you are sending an object (very likely of type Date). The value of type Date is not a String, and so Sequelize is warning you with information like "validatorKey": "not_a_string" and "type": "string violation".

I don't know why you elected to store a timestamp as a String, but part of the fix is to change the column to type Date.

You also mentioned that the column value is filled automatically, but I don't see anywhere where that would take place. Unless you are explicitly setting a default value for the column and then not providing a value when committing the session, these columns will not be automatically filled.

The short answer is, change the column type to DATE and make sure to set a timestamp on the value before committing to the db.

ContentLicense: CC BY-SA 4.0

Body:
Can someone help me I'm having problems inserting a record in the database with sequelize, created_at and updated_at are automatically filled and this is with this error:

"name": "SequelizeValidationError",
"errors": [
    {
        "message": "createdAt cannot be an array or an object",
        "type": "string violation",
        "path": "createdAt",
        "value": "2020-05-28T22:04:45.023Z",
        "origin": "CORE",
        "instance": {
            "id": null,
            "placeId": "1",
            "userId": 3,
            "name": "Alex Santos",
            "email": "customer@gmail.com",
            "documento": "00000000000",
            "phone": "(37)98596-9869",
            "updatedAt": "2020-05-28T22:04:45.023Z",
            "createdAt": "2020-05-28T22:04:45.023Z"
        },
        "validatorKey": "not_a_string",
        "validatorName": null,
        "validatorArgs": []
    },
    {
        "message": "customer.updateAt cannot be null",
        "type": "notNull Violation",
        "path": "updateAt",
        "value": null,
        "origin": "CORE",
        "instance": {
            "id": null,
            "placeId": "1",
            "userId": 3,
            "name": "Alex Santos",
            "email": "customer@gmail.com",
            "documento": "031.682.546-81",
            "phone": "(37)98596-9869",
            "updatedAt": "2020-05-28T22:04:45.023Z",
            "createdAt": "2020-05-28T22:04:45.023Z"
        },
        "validatorKey": "is_null",
        "validatorName": null,
        "validatorArgs": []
    }
]

}

Can someone provide any suggestions to help? I think in customer.js create() function is having some sort of miss from my side.

Could there be any other solution?

customer.js

   /* jshint indent: 1 */

module.exports = function(sequelize, DataTypes) {
    return sequelize.define('customer', {
        id: {
            type: DataTypes.INTEGER(11),
            allowNull: false,
            primaryKey: true,
            autoIncrement: true,
            field: 'id'
        },
        placeId: {
            type: DataTypes.INTEGER(11),
            allowNull: false,
            references: {
                model: 'places',
                key: 'id'
            },
            field: 'place_id'
        },
        userId: {
            type: DataTypes.INTEGER(11),
            allowNull: false,
            references: {
                model: 'users',
                key: 'id'
            },
            field: 'user_id'
        },
        customerId: {
            type: DataTypes.INTEGER(11),
            allowNull: true,
            field: 'customer_id'
        },
        name: {
            type: DataTypes.STRING(100),
            allowNull: false,
            field: 'name'
        },
        email: {
            type: DataTypes.STRING(255),
            allowNull: false,
            field: 'email'
        },
        documento: {
            type: DataTypes.STRING(16),
            allowNull: false,
            defaultValue: '',
            field: 'documento'
        },
        phone: {
            type: DataTypes.STRING(12),
            allowNull: false,
            field: 'phone'
        },
        createdAt: {
            type: DataTypes.STRING(255),
            allowNull: false,
            field: 'created_at'
        },
        updateAt: {
            type: DataTypes.STRING(255),
            allowNull: false,
            field: 'update_at'
        }

    }, {
        tableName: 'customer'
    });
};

CustomerController.js

const Customers = require('./../models/custumers')
const Sequelize = require('sequelize');
const db = require('../../bin/database');
const Customer = new Customers(db, Sequelize);
exports.create = async(req, res) => {
    decodeToken = await jwt.decodeToken(req.headers['x-access-token'])
    let userId = decodeToken.id
    console.log(new Date())
    let { placeId, customerId, name, email, documento, phone } = req.body
    Customer.create({
            placeId,
            userId,
            customerId,
            name,
            email,
            documento,
            phone
        })
        .then((Customer) => {
            return res.status(200).send({ Customer: Customer })
        }).catch(err => {
            res.status(423).send(err);
        });
}


问:
Delete an item (row) from table but keep the unused ID number for a future insertion
I have a database with an "inventory" table which contains products from a shop. Each product is identified using an ID number set in the "ID" column of the table.
I want to be able to delete a product from the table, but keeping the deleted product's id number for future product insertions into the database.
As a demonstration I inserted 4 items and named all of them "test"

And just as an example I named the "deleted" product as "vacio" (empty in spanish) to show the one that i deleted.

Now, if want to add another product in the future, the id number 2 is unused and I want to add the product with that id number instead of 4 (following the given example).

The DELETE query is no good since it erases the id number as well so its a no go.
I thought about checking for the first row of the table that contains the value "vacio" and using the UPDATE query in all fields except id but this doesnt feel "classy" and is not very efficient as It should have to update values a lot of times.
Is there some nice way of doing this?

答:
I would not actually recommend reusing old identifiers. For one, this prevents you from using the auto_increment feature, which mean that you need to manually handle the column for each and every insertion: this adds complexity and is not efficient. Also, it might cause integrity issues in your database if you have other tables referencing the product id.

But if you really want to go that way: I would go for the deletion option. If there are foreign keys referencing the column, make sure that they have the on delete cascade option enabled so data is properly purged from dependent tables when a product is dropped.

Then, you can fill the first available gap the next time your create a new product with the following query:

```<code>insert into products(id, categoria, producto)
select min(id) + 1, 'my new category', 'my new product'
from products p
where not exists (select 1 from products p1 where p1.id = p.id + 1)
</code>```

Body:
I would not actually recommend reusing old identifiers. For one, this prevents you from using the auto_increment feature, which mean that you need to manually handle the column for each and every insertion: this adds complexity and is not efficient. Also, it might cause integrity issues in your database if you have other tables referencing the product id.

But if you really want to go that way: I would go for the deletion option. If there are foreign keys referencing the column, make sure that they have the on delete cascade option enabled so data is properly purged from dependent tables when a product is dropped.

Then, you can fill the first available gap the next time your create a new product with the following query:

insert into products(id, categoria, producto)
select min(id) + 1, 'my new category', 'my new product'
from products p
where not exists (select 1 from products p1 where p1.id = p.id + 1)


问:
Angular Universal + CkEditor5: window is not defined
I'm running an `` application that uses "@ckeditor/ckeditor5-angular": "1.2.3" and a customised build of CKeditor5.  I added SSR (Server Side Rendering - Angular Universal) support:

```<code>ng add @nguniversal/express-engine
</code>```

And when I run npm run dev:ssr I got the following error:

```<code>  ReferenceError: window is not defined
        at Object../node_modules/@ckeditor/ckeditor5-build-classic/build/ckeditor.js (/Users/user1/angular-ssr/dist/angular-ssr/server/main.js:117340:3242)
        at __webpack_require__ (/Users/user1/angular-ssr/dist/angular-ssr/server/main.js:20:30)
        at Object../src/app/post/new-edit-tutorial/new-edit-tutorial.component.ts (/Users/user1/angular-ssr/dist/angular-ssr/server/main.js:228444:23)
        at __webpack_require__ (/Users/user1/angular-ssr/dist/angular-ssr/server/main.js:20:30)
        at Object../src/app/post/post.module.ts (/Users/user1/angular-ssr/dist/angular-ssr/server/main.js:229101:39)
        at __webpack_require__ (/Users/user1/angular-ssr/dist/angular-ssr/server/main.js:20:30)
        at Object../src/app/app.module.ts (/Users/user1/angular-ssr/dist/angular-ssr/server/main.js:227134:23)
        at __webpack_require__ (/Users/user1/angular-ssr/dist/angular-ssr/server/main.js:20:30)
        at Object../src/app/app.server.module.ts (/Users/user1/angular-ssr/dist/angular-ssr/server/main.js:227205:22)
        at __webpack_require__ (/Users/user1/angular-ssr/dist/angular-ssr/server/main.js:20:30)

    A server error has occurred.
</code>```

Is there any way to integrate CkEditor5 with Angular Universal? Or does anybody know any workaround?

Many thanks

答:
The window object is not available during server side rendering because your server (i.e. Node.JS) does not have a window object - it is a browser construct.

During SSR you cannot use code that references browser-specific constructs or objects like window or the DOM.

Body:
I'm running an `` application that uses "@ckeditor/ckeditor5-angular": "1.2.3" and a customised build of CKeditor5.  I added SSR (Server Side Rendering - Angular Universal) support:

ng add @nguniversal/express-engine

And when I run npm run dev:ssr I got the following error:

  ReferenceError: window is not defined
        at Object../node_modules/@ckeditor/ckeditor5-build-classic/build/ckeditor.js (/Users/user1/angular-ssr/dist/angular-ssr/server/main.js:117340:3242)
        at __webpack_require__ (/Users/user1/angular-ssr/dist/angular-ssr/server/main.js:20:30)
        at Object../src/app/post/new-edit-tutorial/new-edit-tutorial.component.ts (/Users/user1/angular-ssr/dist/angular-ssr/server/main.js:228444:23)
        at __webpack_require__ (/Users/user1/angular-ssr/dist/angular-ssr/server/main.js:20:30)
        at Object../src/app/post/post.module.ts (/Users/user1/angular-ssr/dist/angular-ssr/server/main.js:229101:39)
        at __webpack_require__ (/Users/user1/angular-ssr/dist/angular-ssr/server/main.js:20:30)
        at Object../src/app/app.module.ts (/Users/user1/angular-ssr/dist/angular-ssr/server/main.js:227134:23)
        at __webpack_require__ (/Users/user1/angular-ssr/dist/angular-ssr/server/main.js:20:30)
        at Object../src/app/app.server.module.ts (/Users/user1/angular-ssr/dist/angular-ssr/server/main.js:227205:22)
        at __webpack_require__ (/Users/user1/angular-ssr/dist/angular-ssr/server/main.js:20:30)

    A server error has occurred.

Is there any way to integrate CkEditor5 with Angular Universal? Or does anybody know any workaround?

Many thanks


答: You could have a new column ESTADO where you handle if a record is active (1) or inactive (0). Then, to obtain only "undeleted" records you just have to filter by the new column. That way, you also prevent changing the product name to "vacio", which might be useful in the future.</p>

Title: Delete an item (row) from table but keep the unused ID number for a future insertion

Body:
I have a database with an "inventory" table which contains products from a shop. Each product is identified using an ID number set in the "ID" column of the table.
I want to be able to delete a product from the table, but keeping the deleted product's id number for future product insertions into the database.
As a demonstration I inserted 4 items and named all of them "test"

And just as an example I named the "deleted" product as "vacio" (empty in spanish) to show the one that i deleted.

Now, if want to add another product in the future, the id number 2 is unused and I want to add the product with that id number instead of 4 (following the given example).

The DELETE query is no good since it erases the id number as well so its a no go.
I thought about checking for the first row of the table that contains the value "vacio" and using the UPDATE query in all fields except id but this doesnt feel "classy" and is not very efficient as It should have to update values a lot of times.
Is there some nice way of doing this?


问:
Android's BuiltInZoom doesn't work in hybrid app
I'm developing a hybrid app on Android that displays HTML on WebView.
I want to zoom the screen by pinch-out, but BuiltInZoom doesn't work (can't zoom in/out) when I get a touch event on the JavaScript side.
It occurs with Pixel 4 (Android 10), but it works correctly with Pixel 3 (Android 9).

What I've already tried

If I don't get a touch event in JavaScript, I can zoom in and out.

Since pinch event is called on onScale, I can get current span and apply on onDraw.

However, this is undesirable because it does not reflect the "maximum-scale" of the HTML "viewport". I want to control the maximum magnification according to the "viewport".

I get the touch event as follow.

```<code>view.addEventListener('touchstart', (e) => {
  console.log('touchstart');
});
view.addEventListener('touchmove', (e) => {
  console.log('touchmove');
});
</code>```

I set BuiltInZoom to enable on Android.

```<code>webView.getSettings().setBuiltInZoomControls(true);
webView.getSettings().setDisplayZoomControls(true);
webView.getSettings().setSupportZoom(true);
</code>```

Note

It occurs with Pixel 4 (Android 10) and Galaxy Tab S4 (Android 9), but it works correctly with Pixel 3 (Android 9).

I can zoom by using zoom controls, but it was already deprecated.

I can zoom after long pressing on screen with one finger.

I can zoom when placing one finger on an element that I don't get touch event.

onScale is called whenever I operate pinch action.

WebViewClient.onScaleChanged is only called when it can be scaled.

I change the "maximum-scale" of the HTML "viewport" dynamically because some pages are allowed to be zoomed and others are not.

答:
I can zoom by ignoring ACTION_POINTER_DOWN in WebView.onTouchEvent.
But suddenly it's zoomed largely because there is no position.</p>

```<code>@Override
public boolean onTouchEvent(MotionEvent ev) {

    if (ev.getActionMasked() == MotionEvent.ACTION_POINTER_DOWN) {
        return false;
    }

    super.onTouchEvent(ev);

    return true;
}
</code>```

Body:
I'm developing a hybrid app on Android that displays HTML on WebView.
I want to zoom the screen by pinch-out, but BuiltInZoom doesn't work (can't zoom in/out) when I get a touch event on the JavaScript side.
It occurs with Pixel 4 (Android 10), but it works correctly with Pixel 3 (Android 9).

What I've already tried

If I don't get a touch event in JavaScript, I can zoom in and out.

Since pinch event is called on onScale, I can get current span and apply on onDraw.

However, this is undesirable because it does not reflect the "maximum-scale" of the HTML "viewport". I want to control the maximum magnification according to the "viewport".

I get the touch event as follow.

view.addEventListener('touchstart', (e) => {
  console.log('touchstart');
});
view.addEventListener('touchmove', (e) => {
  console.log('touchmove');
});

I set BuiltInZoom to enable on Android.

webView.getSettings().setBuiltInZoomControls(true);
webView.getSettings().setDisplayZoomControls(true);
webView.getSettings().setSupportZoom(true);

Note

It occurs with Pixel 4 (Android 10) and Galaxy Tab S4 (Android 9), but it works correctly with Pixel 3 (Android 9).

I can zoom by using zoom controls, but it was already deprecated.

I can zoom after long pressing on screen with one finger.

I can zoom when placing one finger on an element that I don't get touch event.

onScale is called whenever I operate pinch action.

WebViewClient.onScaleChanged is only called when it can be scaled.

I change the "maximum-scale" of the HTML "viewport" dynamically because some pages are allowed to be zoomed and others are not.

Body:
I can zoom by ignoring ACTION_POINTER_DOWN in WebView.onTouchEvent.
But suddenly it's zoomed largely because there is no position.

@Override
public boolean onTouchEvent(MotionEvent ev) {

    if (ev.getActionMasked() == MotionEvent.ACTION_POINTER_DOWN) {
        return false;
    }

    super.onTouchEvent(ev);

    return true;
}


问:
Form validation not working when appended by D3
I built a form with radio buttons using d3 as below:

var rating_form = d3.select("body")
  .append('form')
  .attr('class', 'rating');

 // Appending up and down vote radio button
 var radio_groups = rating_form.append('div').attr('class', 'form-group');

 // Radio for up
 var radio_grp_chk = radio_groups
  .append('div')
  .attr('class', 'form-check form-check-inline upvote');
 radio_grp_chk
  .append('input')
  .attr('class', 'form-check-input')
  .attr('type', 'radio')
  .attr('name', 'voting-radio')
  .attr('value', 'thumbup')
  .attr("required", "");
 radio_grp_chk.append('span').text("upvote");

 // Radio for down
 var radio_grp_chk2 = radio_groups
  .append('div')
  .attr('class', 'form-check form-check-inline downvote');
 radio_grp_chk2
  .append('input')
  .attr('class', 'form-check-input')
  .attr('type', 'radio')
  .attr('name', 'voting-radio')
  .attr('value', 'thumbdown')
  .attr("required", "");
 radio_grp_chk2.append('span').text("downvote");

 // Appending text area
 rating_form
  .append('div')
  .attr('class', 'form-group')
  .append('textarea')
  .attr('class', 'form-control feedback-text')
  .attr('placeholder', 'Enter your text...');

 // Submit button
 rating_form
  .append('button')
  .attr('type', 'button')
  .attr('class', 'btn btn-primary rating-btn')
  .text('Submit!');```
<pre class="snippet-code-html lang-html prettyprint-override"><code><!DOCTYPE html>

<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <!-- bootstrap -->
    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css"
        crossorigin="anonymous">
</head>

<body>
    <script src="https://d3js.org/d3.v5.min.js"></script>
    <!-- jQuery -->
    <script src="https://code.jquery.com/jquery-3.5.0.min.js" crossorigin="anonymous"></script>
</body></code>```

For the input radio button, I add .attr("required", "") to make it compulsory to select before submitting. However, when I don't select the radio button and click submit, there is no error message that should appear.

How do I fix this?

答:
The problem is not your .attr("required", ""), the issue is just that your button's type should be "submit" instead of "button":

```<code>rating_form
    .append('button')
    .attr('type', 'submit')
    //etc...
</code>```

Since "submit" is the default type you can also just remove the method .attr('type', 'button').

Here is your code with that change:

var rating_form = d3.select("body")
  .append('form')
  .attr('class', 'rating');

 // Appending up and down vote radio button
 var radio_groups = rating_form.append('div').attr('class', 'form-group');

 // Radio for up
 var radio_grp_chk = radio_groups
  .append('div')
  .attr('class', 'form-check form-check-inline upvote');
 radio_grp_chk
  .append('input')
  .attr('class', 'form-check-input')
  .attr('type', 'radio')
  .attr('name', 'voting-radio')
  .attr('value', 'thumbup')
  .attr("required", "");
 radio_grp_chk.append('span').text("upvote");

 // Radio for down
 var radio_grp_chk2 = radio_groups
  .append('div')
  .attr('class', 'form-check form-check-inline downvote');
 radio_grp_chk2
  .append('input')
  .attr('class', 'form-check-input')
  .attr('type', 'radio')
  .attr('name', 'voting-radio')
  .attr('value', 'thumbdown')
  .attr("required", "");
 radio_grp_chk2.append('span').text("downvote");

 // Appending text area
 rating_form
  .append('div')
  .attr('class', 'form-group')
  .append('textarea')
  .attr('class', 'form-control feedback-text')
  .attr('placeholder', 'Enter your text...');

 // Submit button
 rating_form
  .append('button')
  .attr('type', 'submit')
  .attr('class', 'btn btn-primary rating-btn')
  .text('Submit!');```
<pre class="snippet-code-html lang-html prettyprint-override"><code><!DOCTYPE html>

<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <!-- bootstrap -->
    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css"
        crossorigin="anonymous">
</head>

<body>
    <script src="https://d3js.org/d3.v5.min.js"></script>
    <!-- jQuery -->
    <script src="https://code.jquery.com/jquery-3.5.0.min.js" crossorigin="anonymous"></script>
</body></code>```

Body:
I built a form with radio buttons using d3 as below:

var rating_form = d3.select("body")
  .append('form')
  .attr('class', 'rating');

 // Appending up and down vote radio button
 var radio_groups = rating_form.append('div').attr('class', 'form-group');

 // Radio for up
 var radio_grp_chk = radio_groups
  .append('div')
  .attr('class', 'form-check form-check-inline upvote');
 radio_grp_chk
  .append('input')
  .attr('class', 'form-check-input')
  .attr('type', 'radio')
  .attr('name', 'voting-radio')
  .attr('value', 'thumbup')
  .attr("required", "");
 radio_grp_chk.append('span').text("upvote");

 // Radio for down
 var radio_grp_chk2 = radio_groups
  .append('div')
  .attr('class', 'form-check form-check-inline downvote');
 radio_grp_chk2
  .append('input')
  .attr('class', 'form-check-input')
  .attr('type', 'radio')
  .attr('name', 'voting-radio')
  .attr('value', 'thumbdown')
  .attr("required", "");
 radio_grp_chk2.append('span').text("downvote");

 // Appending text area
 rating_form
  .append('div')
  .attr('class', 'form-group')
  .append('textarea')
  .attr('class', 'form-control feedback-text')
  .attr('placeholder', 'Enter your text...');

 // Submit button
 rating_form
  .append('button')
  .attr('type', 'button')
  .attr('class', 'btn btn-primary rating-btn')
  .text('Submit!');

<!DOCTYPE html>

    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">

    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css"
        crossorigin="anonymous">

For the input radio button, I add .attr("required", "") to make it compulsory to select before submitting. However, when I don't select the radio button and click submit, there is no error message that should appear.

How do I fix this?

Body:
The problem is not your .attr("required", ""), the issue is just that your button's type should be "submit" instead of "button":

rating_form
    .append('button')
    .attr('type', 'submit')
    //etc...

Since "submit" is the default type you can also just remove the method .attr('type', 'button').

Here is your code with that change:

var rating_form = d3.select("body")
  .append('form')
  .attr('class', 'rating');

 // Appending up and down vote radio button
 var radio_groups = rating_form.append('div').attr('class', 'form-group');

 // Radio for up
 var radio_grp_chk = radio_groups
  .append('div')
  .attr('class', 'form-check form-check-inline upvote');
 radio_grp_chk
  .append('input')
  .attr('class', 'form-check-input')
  .attr('type', 'radio')
  .attr('name', 'voting-radio')
  .attr('value', 'thumbup')
  .attr("required", "");
 radio_grp_chk.append('span').text("upvote");

 // Radio for down
 var radio_grp_chk2 = radio_groups
  .append('div')
  .attr('class', 'form-check form-check-inline downvote');
 radio_grp_chk2
  .append('input')
  .attr('class', 'form-check-input')
  .attr('type', 'radio')
  .attr('name', 'voting-radio')
  .attr('value', 'thumbdown')
  .attr("required", "");
 radio_grp_chk2.append('span').text("downvote");

 // Appending text area
 rating_form
  .append('div')
  .attr('class', 'form-group')
  .append('textarea')
  .attr('class', 'form-control feedback-text')
  .attr('placeholder', 'Enter your text...');

 // Submit button
 rating_form
  .append('button')
  .attr('type', 'submit')
  .attr('class', 'btn btn-primary rating-btn')
  .text('Submit!');

<!DOCTYPE html>

<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <!-- bootstrap -->
    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css"
        crossorigin="anonymous">
</head>

<body>
    <script src="https://d3js.org/d3.v5.min.js"></script>
    <!-- jQuery -->
    <script src="https://code.jquery.com/jquery-3.5.0.min.js" crossorigin="anonymous"></script>
</body>


问:
Adjust spacing around paragraph (within a div) so that the space on either side is always equal between divs on the right and left
I have three divs, aligned on a single row as columns, using a flex container.

The first and third columns have a small amount of text in each, the middle column has a large paragraph.

What I would like to do is to align the text in the middle div so that the space around between it and the first and third divs is always equal, even when the width of the page changes and the words wrap to the next line.

By default, the word wrapping behaviour means that you can end up with a lot of whitespace on the right of the div, which isn't equal to the whitespace on the left (because of the varying length of words). How do I ensure the spacing adjusts based on the longest word (I assume the longest word), so it it always equal?

Here is some example code:

.container {
  display: flex;
}```
<pre class="snippet-code-html lang-html prettyprint-override"><code><div class="container">

  <div class="column1">
    <p>
      Some content
    </p>
  </div>

  <div class="column2">
    <p>
      There is more content in this div than the other divs. Blah, blah, blah, blah, blah, blah...
    </p>
  </div>

  <div class="column3">
    <p>
      Some content
    </p>
  </div>

</div></code>```

If you expand and shrink the window, you can see that as the middle column's words get closer to wrapping, the spacing isn't equal on either side of the div; there is less space on the right than the left. This what I would like to resolve, so the spacing is always equal between the divs.

答: I think that you may put a determinated size to the div anthe then a text align for the larga

Body:
I have three divs, aligned on a single row as columns, using a flex container.

The first and third columns have a small amount of text in each, the middle column has a large paragraph.

What I would like to do is to align the text in the middle div so that the space around between it and the first and third divs is always equal, even when the width of the page changes and the words wrap to the next line.

By default, the word wrapping behaviour means that you can end up with a lot of whitespace on the right of the div, which isn't equal to the whitespace on the left (because of the varying length of words). How do I ensure the spacing adjusts based on the longest word (I assume the longest word), so it it always equal?

Here is some example code:

.container {
  display: flex;
}

      Some content

      There is more content in this div than the other divs. Blah, blah, blah, blah, blah, blah...

      Some content

If you expand and shrink the window, you can see that as the middle column's words get closer to wrapping, the spacing isn't equal on either side of the div; there is less space on the right than the left. This what I would like to resolve, so the spacing is always equal between the divs.


问:
How can I do a folded ribbon effect using CSS?
I'm trying to convert an image based info-graphic to html and css. I can get 90% there, but am looking for some help with the folded ribbon effect .
The info-graphic has Yes/No directions like this:

The end of the "ribbon" is folded under and pokes out the bottom with a darker shade of the primary colour.

Here is what i have so far:

```
<pre class="snippet-code-html lang-html prettyprint-override"><code>    <div class="container">
        <div class="child header">Header</div>
        <div class="child leftcol">
            <div class="greenleft">Yes</div>
            <p>Content on the left</p>
        </div>
        <div class="child rightcol">
            <div class="redright">No</div>
            <p>Content on the right</p>
        </div>
    </div></code>```

答:
I would do it like below:

.box {
  width: 200px;
  padding: 10px 20px;
  margin: 40px 80px;
  color: #fff;
  text-align: right;
  background: #7fbc03;
  border-radius: 8px;
  position: relative;
  z-index: 0;
}

.box::before,
.box::after {
  content: "";
  position: absolute;
  z-index: -1;
  top: 0;
  bottom: 0;
  background: inherit;
  border-radius:inherit;
  border-bottom-left-radius:0;
  transform-origin: top left;
}

.box::before {
  left: 0;
  right: 20%;
  transform: skewX(-40deg);
}

.box::after {
  z-index: -2;
  left: 1px;
  height: 130%; /* ~ 100%/cos(40deg) */
  width: 40px;
  filter: brightness(0.7);
  transform: rotate(40deg);
}

.right {
  text-align: left;
  background: #cd1719;
}

.right::before {
  right: 0;
  left: 20%;
  border-bottom-right-radius:0;
  border-bottom-left-radius:inherit;
  transform: skewX(40deg);
}

.right::after {
  right: 1px;
  left: auto;
  transform-origin: top right;
  border-bottom-right-radius:0;
  border-bottom-left-radius:inherit;
  transform: rotate(-40deg);
}```
<pre class="snippet-code-html lang-html prettyprint-override"><code><div class="box">YES</div>

<div class="box right">NO</div>

<div class="box right" style="background:lightblue;">Two <br> lines</div>

<div class="box" style="background:purple;width:auto;">full width</div>

<div class="box right" style="background:orange;width:auto;display:inline-block">auto width</div></code>```

Body:
I'm trying to convert an image based info-graphic to html and css. I can get 90% there, but am looking for some help with the folded ribbon effect .
The info-graphic has Yes/No directions like this:

The end of the "ribbon" is folded under and pokes out the bottom with a darker shade of the primary colour.

Here is what i have so far:

Header

Yes

Content on the left

No

Content on the right

Body:
I would do it like below:

.box {
  width: 200px;
  padding: 10px 20px;
  margin: 40px 80px;
  color: #fff;
  text-align: right;
  background: #7fbc03;
  border-radius: 8px;
  position: relative;
  z-index: 0;
}

.box::before,
.box::after {
  content: "";
  position: absolute;
  z-index: -1;
  top: 0;
  bottom: 0;
  background: inherit;
  border-radius:inherit;
  border-bottom-left-radius:0;
  transform-origin: top left;
}

.box::before {
  left: 0;
  right: 20%;
  transform: skewX(-40deg);
}

.box::after {
  z-index: -2;
  left: 1px;
  height: 130%; /* ~ 100%/cos(40deg) */
  width: 40px;
  filter: brightness(0.7);
  transform: rotate(40deg);
}

.right {
  text-align: left;
  background: #cd1719;
}

.right::before {
  right: 0;
  left: 20%;
  border-bottom-right-radius:0;
  border-bottom-left-radius:inherit;
  transform: skewX(40deg);
}

.right::after {
  right: 1px;
  left: auto;
  transform-origin: top right;
  border-bottom-right-radius:0;
  border-bottom-left-radius:inherit;
  transform: rotate(-40deg);
}

<div class="box">YES</div>

<div class="box right">NO</div>

<div class="box right" style="background:lightblue;">Two <br> lines</div>

<div class="box" style="background:purple;width:auto;">full width</div>

<div class="box right" style="background:orange;width:auto;display:inline-block">auto width</div>


问:
vim: termguicolors with xterm-true-color still causing problems
I have seen a multitiude of posts where not enabling 'tgc' with :

```<code>if exists('+termguicolors')
   let &t_8f =  "\<Esc>[38:2:%lu:%lu:%lum"
   let &t_8b =  "\<Esc>[48:2:%lu:%lu:%lum"
   " let &t_8f =  "\<Esc>[38:2;%lu;%lu;%lum" ( I have tried both ':' and ';' )
   " let &t_8b =  "\<Esc>[48:2;%lu;%lu;%lum"
   set t_Co=256
   set termguicolors
   " colorscheme gruvbox " color scheme
 endif
</code>```

causes vim to have weird color output - usually with tmux.

Initially I found success with this too. Until one fine day (seriously!) vim starts behaving weird, but in a different way. It goes monochrome.

If, I don't set it, i.e se notgc , I actually get the right colorscheme. This is exactly the same in vim + tmux usage as well.

But, when I use vim + tmux, if I, say, kill a pane, or reload ~/tmux.config, existing vim sessions get weird again!

Here
 is a look at one such occurance, the left is a newly opened buffer, while the right one, with the same settings, suddenly goes weird.

My settings :

This is my company work server, I don't have su permissions.

```<code>$ cat /proc/version
Linux version 2.6.32-504.30.3.el6.x86_64 (mockbuild@c6b8.bsys.dev.centos.org) (gcc version 4.4.7 20120313 (Red Hat 4.4.7-11) (GCC) ) #1 SMP Wed Jul 15 10:13:09 UTC 2015
</code>```

VIM

```<code>vim --version
VIM - Vi IMproved 8.1 (2018 May 18, compiled Jul 26 2019 22:56:22)
Included patches: 1
Compiled by bob@c6x64
Huge version with GTK2 GUI.  Features included (+) or not (-):
+acl               +farsi             +mouse_sgr         -tag_any_white
+arabic            +file_in_path      -mouse_sysmouse    -tcl
+autocmd           +find_in_path      +mouse_urxvt       +termguicolors
-autoservername    +float             +mouse_xterm       +terminal
+balloon_eval      +folding           +multi_byte        +terminfo
+balloon_eval_term -footer            +multi_lang        +termresponse
+browse            +fork()            -mzscheme          +textobjects
++builtin_terms    +gettext           +netbeans_intg     +timers                                                                                [25/126]
+byte_offset       -hangul_input      +num64             +title
+channel           +iconv             +packages          +toolbar
+cindent           +insert_expand     +path_extra        +user_commands
+clientserver      +job               -perl              +vertsplit
+clipboard         +jumplist          +persistent_undo   +virtualedit
+cmdline_compl     +keymap            +postscript        +visual
+cmdline_hist      +lambda            +printer           +visualextra
+cmdline_info      +langmap           +profile           +viminfo
+comments          +libcall           -python            +vreplace
+conceal           +linebreak         -python3           +wildignore
+cryptv            +lispindent        +quickfix          +wildmenu
+cscope            +listcmds          +reltime           +windows
+cursorbind        +localmap          +rightleft         +writebackup
+cursorshape       -lua               -ruby              +X11
+dialog_con_gui    +menu              +scrollbind        -xfontset
+diff              +mksession         +signs             +xim
+dnd               +mouse             +startuptime       +xsmp_interact
-ebcdic            +mouseshape        +statusline        +xterm_clipboard
+emacs_tags        +mouse_dec         -sun_workshop      -xterm_save
+eval              +mouse_gpm         +syntax
+ex_extra          -mouse_jsbterm     +tag_binary
+extra_search      +mouse_netterm     +tag_old_static
   system vimrc file: "$VIM/vimrc"
     user vimrc file: "$HOME/.vimrc"
 2nd user vimrc file: "~/.vim/vimrc"
      user exrc file: "$HOME/.exrc"
  system gvimrc file: "$VIM/gvimrc"
    user gvimrc file: "$HOME/.gvimrc"
2nd user gvimrc file: "~/.vim/gvimrc"
       defaults file: "$VIMRUNTIME/defaults.vim"
    system menu file: "$VIMRUNTIME/menu.vim"
  fall-back for $VIM: "/tools/apps/local/vim/latest/share/vim"
Compilation: gcc -std=gnu99 -c -I. -Iproto -DHAVE_CONFIG_H -DFEAT_GUI_GTK  -pthread -I/usr/include/gtk-2.0 -I/usr/lib64/gtk-2.0/include -I/usr/include/atk-1.0 -I/usr/include/cairo -I/usr/include/gdk-pixbuf-2.0 -I/usr/include/pango-1.0 -I/usr/include/glib-2.0 -I/usr/lib64/glib-2.0/include -I/usr/include/pixman-1 -I/usr/include/freety
pe2 -I/usr/include/libpng12     -O2 -fno-strength-reduce -Wall -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=1
Linking: gcc -std=gnu99   -L/usr/local/lib -Wl,--as-needed -o vim   -pthread -lgtk-x11-2.0 -lgdk-x11-2.0 -latk-1.0 -lgio-2.0 -lpangoft2-1.0 -lpangocairo-1.0 -lgdk_pixb
uf-2.0 -lcairo -lpango-1.0 -lfreetype -lfontconfig -lgobject-2.0 -lgmodule-2.0 -lgthread-2.0 -lrt -lglib-2.0   -lSM -lICE -lXpm -lXt -lX11 -lXdmcp -lSM -lICE  -lm -lti
nfo -lelf -lnsl  -lselinux -lacl -lattr -lgpm

</code>```

The default cshrc had TERM explicitly set as vt100. If I change it to xterm-256color or screen-256color, I actually get good colorschemes within vim, and :set term=$TERM or explicitly to either of the above two, with the same problems showing up.

TMUX
v2.3, tried the following :

```<code>set -g default-terminal "screen/xterm-256color"
set -ga terminal-overrides ",*256col*:Tc"
</code>```

I use gnome-terminal(v2.31.3), I also tried Konsole(v 2.3.3, Qt: 4.6.2, KDE: 4.3.4) -- and here I am not seeing the issue! But, konsole is terribly slow over my vnc connection, which is not the case gnome-terminal, so I decided to stick with it.

-- On color support : No true color support since

```<code>awk 'BEGIN{
    s="/\\/\\/\\/\\/\\"; s=s s s s s s s s;
    for (colnum = 0; colnum<77; colnum++) {
        r = 255-(colnum*255/76);
        g = (colnum*510/76);
        b = (colnum*255/76);
        if (g>255) g = 510-g;
        printf "\033[48;2;%d;%d;%dm", r,g,b;
        printf "\033[38;2;%d;%d;%dm", 255-r,255-g,255-b;
        printf "%s\033[0m", substr(s,colnum+1,1);
    }
    printf "\n";
}
</code>```

returns this.  where as Konsole returns a much smoother output.

Should I ditch gnome-terminal and try some other emulator (which is snappier than Konsole) ? I would really appreciate if a solution can be found within gnome-terminal itself.

I hope I have given all the relevant details,
Thanks

答:
I believe this is in part due to your tmux configuration.  You'll want to set the following in .tmux.conf:

```<code>set -g default-terminal screen-256color
set -ag terminal-overrides ",xterm-256color:Tc"
</code>```

Note that you cannot use a slash in the default terminal option, since it must be a valid terminal type.  I assume all the systems you are logging into have the screen-256color terminal type, but you can check by running infocmp screen-256color, which should print terminal info on success and an error on error.  You may need to install additional packages to add that terminal type.

As far as GNOME Terminal, 2.31 is very old. The VTE version used in GNOME 2 definitely does not support true colors.  Ideally you'll set up your local system to use a modern terminal emulator and log in over SSH instead of using VNC, and things will work.

I will be clear that since you're using CentOS or RHEL 6 here, that virtually any terminal emulator you're trying to use will likely be broken.  This OS is a decade old and will lose security support as of November.  Your best bet, as mentioned, is to use a more modern environment on your laptop or desktop and log in over SSH.

Body:
I have seen a multitiude of posts where not enabling 'tgc' with :

if exists('+termguicolors')
   let &t_8f =  "\<Esc>[38:2:%lu:%lu:%lum"
   let &t_8b =  "\<Esc>[48:2:%lu:%lu:%lum"
   " let &t_8f =  "\<Esc>[38:2;%lu;%lu;%lum" ( I have tried both ':' and ';' )
   " let &t_8b =  "\<Esc>[48:2;%lu;%lu;%lum"
   set t_Co=256
   set termguicolors
   " colorscheme gruvbox " color scheme
 endif

causes vim to have weird color output - usually with tmux.

Initially I found success with this too. Until one fine day (seriously!) vim starts behaving weird, but in a different way. It goes monochrome.

If, I don't set it, i.e se notgc , I actually get the right colorscheme. This is exactly the same in vim + tmux usage as well.

But, when I use vim + tmux, if I, say, kill a pane, or reload ~/tmux.config, existing vim sessions get weird again!

Here
 is a look at one such occurance, the left is a newly opened buffer, while the right one, with the same settings, suddenly goes weird.

My settings :

This is my company work server, I don't have su permissions.

$ cat /proc/version
Linux version 2.6.32-504.30.3.el6.x86_64 (mockbuild@c6b8.bsys.dev.centos.org) (gcc version 4.4.7 20120313 (Red Hat 4.4.7-11) (GCC) ) #1 SMP Wed Jul 15 10:13:09 UTC 2015

VIM

vim --version
VIM - Vi IMproved 8.1 (2018 May 18, compiled Jul 26 2019 22:56:22)
Included patches: 1
Compiled by bob@c6x64
Huge version with GTK2 GUI.  Features included (+) or not (-):
+acl               +farsi             +mouse_sgr         -tag_any_white
+arabic            +file_in_path      -mouse_sysmouse    -tcl
+autocmd           +find_in_path      +mouse_urxvt       +termguicolors
-autoservername    +float             +mouse_xterm       +terminal
+balloon_eval      +folding           +multi_byte        +terminfo
+balloon_eval_term -footer            +multi_lang        +termresponse
+browse            +fork()            -mzscheme          +textobjects
++builtin_terms    +gettext           +netbeans_intg     +timers                                                                                [25/126]
+byte_offset       -hangul_input      +num64             +title
+channel           +iconv             +packages          +toolbar
+cindent           +insert_expand     +path_extra        +user_commands
+clientserver      +job               -perl              +vertsplit
+clipboard         +jumplist          +persistent_undo   +virtualedit
+cmdline_compl     +keymap            +postscript        +visual
+cmdline_hist      +lambda            +printer           +visualextra
+cmdline_info      +langmap           +profile           +viminfo
+comments          +libcall           -python            +vreplace
+conceal           +linebreak         -python3           +wildignore
+cryptv            +lispindent        +quickfix          +wildmenu
+cscope            +listcmds          +reltime           +windows
+cursorbind        +localmap          +rightleft         +writebackup
+cursorshape       -lua               -ruby              +X11
+dialog_con_gui    +menu              +scrollbind        -xfontset
+diff              +mksession         +signs             +xim
+dnd               +mouse             +startuptime       +xsmp_interact
-ebcdic            +mouseshape        +statusline        +xterm_clipboard
+emacs_tags        +mouse_dec         -sun_workshop      -xterm_save
+eval              +mouse_gpm         +syntax
+ex_extra          -mouse_jsbterm     +tag_binary
+extra_search      +mouse_netterm     +tag_old_static
   system vimrc file: "$VIM/vimrc"
     user vimrc file: "$HOME/.vimrc"
 2nd user vimrc file: "~/.vim/vimrc"
      user exrc file: "$HOME/.exrc"
  system gvimrc file: "$VIM/gvimrc"
    user gvimrc file: "$HOME/.gvimrc"
2nd user gvimrc file: "~/.vim/gvimrc"
       defaults file: "$VIMRUNTIME/defaults.vim"
    system menu file: "$VIMRUNTIME/menu.vim"
  fall-back for $VIM: "/tools/apps/local/vim/latest/share/vim"
Compilation: gcc -std=gnu99 -c -I. -Iproto -DHAVE_CONFIG_H -DFEAT_GUI_GTK  -pthread -I/usr/include/gtk-2.0 -I/usr/lib64/gtk-2.0/include -I/usr/include/atk-1.0 -I/usr/include/cairo -I/usr/include/gdk-pixbuf-2.0 -I/usr/include/pango-1.0 -I/usr/include/glib-2.0 -I/usr/lib64/glib-2.0/include -I/usr/include/pixman-1 -I/usr/include/freety
pe2 -I/usr/include/libpng12     -O2 -fno-strength-reduce -Wall -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=1
Linking: gcc -std=gnu99   -L/usr/local/lib -Wl,--as-needed -o vim   -pthread -lgtk-x11-2.0 -lgdk-x11-2.0 -latk-1.0 -lgio-2.0 -lpangoft2-1.0 -lpangocairo-1.0 -lgdk_pixb
uf-2.0 -lcairo -lpango-1.0 -lfreetype -lfontconfig -lgobject-2.0 -lgmodule-2.0 -lgthread-2.0 -lrt -lglib-2.0   -lSM -lICE -lXpm -lXt -lX11 -lXdmcp -lSM -lICE  -lm -lti
nfo -lelf -lnsl  -lselinux -lacl -lattr -lgpm

The default cshrc had TERM explicitly set as vt100. If I change it to xterm-256color or screen-256color, I actually get good colorschemes within vim, and :set term=$TERM or explicitly to either of the above two, with the same problems showing up.

TMUX
v2.3, tried the following :

set -g default-terminal "screen/xterm-256color"
set -ga terminal-overrides ",*256col*:Tc"

I use gnome-terminal(v2.31.3), I also tried Konsole(v 2.3.3, Qt: 4.6.2, KDE: 4.3.4) -- and here I am not seeing the issue! But, konsole is terribly slow over my vnc connection, which is not the case gnome-terminal, so I decided to stick with it.

-- On color support : No true color support since

awk 'BEGIN{
    s="/\\/\\/\\/\\/\\"; s=s s s s s s s s;
    for (colnum = 0; colnum<77; colnum++) {
        r = 255-(colnum*255/76);
        g = (colnum*510/76);
        b = (colnum*255/76);
        if (g>255) g = 510-g;
        printf "\033[48;2;%d;%d;%dm", r,g,b;
        printf "\033[38;2;%d;%d;%dm", 255-r,255-g,255-b;
        printf "%s\033[0m", substr(s,colnum+1,1);
    }
    printf "\n";
}

returns this.  where as Konsole returns a much smoother output.

Should I ditch gnome-terminal and try some other emulator (which is snappier than Konsole) ? I would really appreciate if a solution can be found within gnome-terminal itself.

I hope I have given all the relevant details,
Thanks

Body:
I believe this is in part due to your tmux configuration.  You'll want to set the following in .tmux.conf:

set -g default-terminal screen-256color
set -ag terminal-overrides ",xterm-256color:Tc"

Note that you cannot use a slash in the default terminal option, since it must be a valid terminal type.  I assume all the systems you are logging into have the screen-256color terminal type, but you can check by running infocmp screen-256color, which should print terminal info on success and an error on error.  You may need to install additional packages to add that terminal type.

As far as GNOME Terminal, 2.31 is very old. The VTE version used in GNOME 2 definitely does not support true colors.  Ideally you'll set up your local system to use a modern terminal emulator and log in over SSH instead of using VNC, and things will work.

I will be clear that since you're using CentOS or RHEL 6 here, that virtually any terminal emulator you're trying to use will likely be broken.  This OS is a decade old and will lose security support as of November.  Your best bet, as mentioned, is to use a more modern environment on your laptop or desktop and log in over SSH.


问:
For loop in Each Row of Union
```<code>Function Atotal(AB As Range, values As Range) As Double
    Atotal = 0
    Items = Union(AB.Cells, values.Cells)

    For Each hrow In Items.Rows
       ' If AB cell.Value =="A" then
       ' Atotal = Atotal + values cell.Value
    Next hrow
End Function
</code>```

For Example:

```<code>AB  |   VAL
------------
A   |   5
A   |   2
B   |   5
A   |   3
B   |   1
</code>```

Atotal should be 10 (=5+2+3)

How to get this? How to loop through each row of Union and get the values of different range?

答:
There is no need to use Union in this process.

```<code>Function Atotal(AB As Range, values As Range) As Double
    Atotal = 0

    Dim i As Integer
    For i = 1 To values.Rows.Count
        If AB.Cells(i, 1) = "A" Then
            Atotal = Atotal + values.Cells(i, 1).Value
        End If
    Next i

End Function
</code>```

Title: For loop in Each Row of Union

Body:
Function Atotal(AB As Range, values As Range) As Double
    Atotal = 0
    Items = Union(AB.Cells, values.Cells)

    For Each hrow In Items.Rows
       ' If AB cell.Value =="A" then
       ' Atotal = Atotal + values cell.Value
    Next hrow
End Function

For Example:

AB  |   VAL
------------
A   |   5
A   |   2
B   |   5
A   |   3
B   |   1

Atotal should be 10 (=5+2+3)

How to get this? How to loop through each row of Union and get the values of different range?

Body:
There is no need to use Union in this process.

Function Atotal(AB As Range, values As Range) As Double
    Atotal = 0

    Dim i As Integer
    For i = 1 To values.Rows.Count
        If AB.Cells(i, 1) = "A" Then
            Atotal = Atotal + values.Cells(i, 1).Value
        End If
    Next i

End Function


问:
Alexa.Discovery response: no device detected by Alexa
I am implementing my Alexa Home Skill using AWS Lambda.

Given the following request I receive when I try to detect new devices on Alexa Skil test page:

```<code>{directive={header={namespace=Alexa.Discovery, name=Discover, payloadVersion=3, messageId=0160c7e7-031f-47ee-a1d9-a23f38f87a9e}, payload={scope={type=BearerToken, token=...}}}}
</code>```

I respond with the following:

```<code>{
    "event": {
        "payload": {
            "endpoints": [
                {
                    "displayCategories": [
                        "SMARTPLUG"
                    ],
                    "capabilities": [
                        {
                            "type": "AlexaInterface",
                            "interface": "Alexa",
                            "version": "3"
                        },
                        {
                            "type": "AlexaInterface",
                            "interface": "Alexa.PowerController",
                            "version": "3",
                            "properties": {
                                "retrievable": true,
                                "supported": [
                                    {
                                        "name": "powerState"
                                    }
                                ],
                                "proactivelyReported": true
                            }
                        },
                        {
                            "type": "AlexaInterface",
                            "interface": "Alexa.EndpointHealth",
                            "version": "3",
                            "properties": {
                                "retrievable": true,
                                "supported": [
                                    {
                                        "name": "connectivity"
                                    }
                                ],
                                "proactivelyReported": true
                            }
                        }
                    ],
                    "manufacturerName": "mirko.io",
                    "endpointId": "ca84ef6d-53b1-430a-8a5e-a62f174eac5e",
                    "description": "mirko.io forno (id: ca84ef6d-53b1-430a-8a5e-a62f174eac5e)",
                    "friendlyName": "forno"
                }
            ]
        },
        "header": {
            "payloadVersion": "3",
            "namespace": "Alexa.Discovery",
            "name": "Discover.Response",
            "messageId": "c0555cc8-ad7a-4377-b310-9de9b9ab6282"
        }
    }
}
</code>```

Despite that, for some reasons Alexa answers that it did not find any new device.
I may be mistaken but I am pretty sure it used to work before I decided to add the Alexa.EndpointHealth interface.

答:
Your response object looks right to me, except the extra "endpoint" field.

```<code>"endpoint": {
            "endpointId": "INVALID",
            "scope": {
                "type": "BearerToken",
                "token": "INVALID"
            }
        }
</code>```

There's no such field in the Alexa.Discovery documentation. Try removing it and see if it resolves the issue.

Body:
I am implementing my Alexa Home Skill using AWS Lambda.

Given the following request I receive when I try to detect new devices on Alexa Skil test page:

{directive={header={namespace=Alexa.Discovery, name=Discover, payloadVersion=3, messageId=0160c7e7-031f-47ee-a1d9-a23f38f87a9e}, payload={scope={type=BearerToken, token=...}}}}

I respond with the following:

{
    "event": {
        "payload": {
            "endpoints": [
                {
                    "displayCategories": [
                        "SMARTPLUG"
                    ],
                    "capabilities": [
                        {
                            "type": "AlexaInterface",
                            "interface": "Alexa",
                            "version": "3"
                        },
                        {
                            "type": "AlexaInterface",
                            "interface": "Alexa.PowerController",
                            "version": "3",
                            "properties": {
                                "retrievable": true,
                                "supported": [
                                    {
                                        "name": "powerState"
                                    }
                                ],
                                "proactivelyReported": true
                            }
                        },
                        {
                            "type": "AlexaInterface",
                            "interface": "Alexa.EndpointHealth",
                            "version": "3",
                            "properties": {
                                "retrievable": true,
                                "supported": [
                                    {
                                        "name": "connectivity"
                                    }
                                ],
                                "proactivelyReported": true
                            }
                        }
                    ],
                    "manufacturerName": "mirko.io",
                    "endpointId": "ca84ef6d-53b1-430a-8a5e-a62f174eac5e",
                    "description": "mirko.io forno (id: ca84ef6d-53b1-430a-8a5e-a62f174eac5e)",
                    "friendlyName": "forno"
                }
            ]
        },
        "header": {
            "payloadVersion": "3",
            "namespace": "Alexa.Discovery",
            "name": "Discover.Response",
            "messageId": "c0555cc8-ad7a-4377-b310-9de9b9ab6282"
        }
    }
}

Despite that, for some reasons Alexa answers that it did not find any new device.
I may be mistaken but I am pretty sure it used to work before I decided to add the Alexa.EndpointHealth interface.

Body:
Your response object looks right to me, except the extra "endpoint" field.

"endpoint": {
            "endpointId": "INVALID",
            "scope": {
                "type": "BearerToken",
                "token": "INVALID"
            }
        }

There's no such field in the Alexa.Discovery documentation. Try removing it and see if it resolves the issue.


答:
Let us try pd.concat

```<code>yourdf=pd.concat(d).reset_index(level=0)
</code>```

Title: Get dataframe from confusing dictionary data structure

Body:
I have a dictionary like on below :

    {1:            ds       yhat  yhat_lower  yhat_upper
30 2015-08-09  49.908927   31.632462   66.742083
31 2015-08-16  49.750056   34.065527   67.069122
32 2015-08-23  49.591185   32.620258   67.403908
33 2015-08-30  49.432314   32.257891   67.541757
34 2015-09-06  72.395618   55.612973   89.711030
35 2015-09-13  49.114572   32.199945   66.255518
36 2015-09-20  48.955701   30.759960   66.118051,
    2:            ds       yhat  yhat_lower  yhat_upper
30 2015-08-09  38.001931   23.583157   51.291784
31 2015-08-16  37.922999   25.370967   50.504328
32 2015-08-23  37.844068   23.743860   51.143868
33 2015-08-30  37.765136   24.903955   50.309284
34 2015-09-06  39.227773   25.089493   52.719935
35 2015-09-13  37.607273   24.370609   51.313454
36 2015-09-20  37.528341   23.395560   50.499454}

Want to get dataframe  like this output

ProductCode    ds         yhat       yhat_lower  yhat_upper
  1           2015-08-09  49.908927   31.632462   66.742083
  1           2015-08-16  49.750056   34.065527   67.069122
  1           2015-08-23  49.591185   32.620258   67.403908
  1           2015-08-30  49.432314   32.257891   67.541757
  1           2015-09-06  72.395618   55.612973   89.711030
  1           2015-09-13  49.114572   32.199945   66.255518
  1           2015-09-20  48.955701   30.759960   66.118051,
  2           2015-08-09  38.001931   23.583157   51.291784
  2           2015-08-16  37.922999   25.370967   50.504328
  2           2015-08-23  37.844068   23.743860   51.143868
  2           2015-08-30  37.765136   24.903955   50.309284
  2           2015-09-06  39.227773   25.089493   52.719935
  2           2015-09-13  37.607273   24.370609   51.313454
  2           2015-09-20  37.528341   23.395560   50.499454

My failed attempt:
 new_df = pd.DataFrame(df.items(), columns=['ProductCode', 'yhat'])
 print(new_df)

      ProdutCode    yhat

     0  1        ds yhat yhat_lower yhat_upp...
     1  2        ds yhat yhat_lower yhat_upp...

in the dictionary all the ds yhat yhat_lower and yhat_upper head and their values were taken as dict.values(). How to separate those letter part as Dataframe columns and numeric value part is their own column values?

Body:
Let us try pd.concat

yourdf=pd.concat(d).reset_index(level=0)


问:
How do I format datetime data to fit google calendar api's date field?
Goal: create a Google Calendar event.

Blocker: the date formatting.

background: I'm trying to create a meal planner that takes recipes from a given database and creates events with their name in a google calendar. The database looks like this:

```<code>d = {'recipe_id': ['carrot salad', 'leek fritters'], 'meal_date': ['2020-05-28 22:28:01.204464+00:00', '2020-05-29 22:28:01.204464+00:00']}
df = pd.DataFrame(data=d)
</code>```

the meal date is a product of two

```<code>today_date = datetime.datetime.utcnow().isoformat() + 'Z'
df['menu_date'] = today_date
df['menu_date'] = pd.to_datetime(df['menu_date'])
df['meal_date'] = df['menu_date'] + df['meal'].apply(pd.offsets.Day)
</code>```

Where 'meal' is just a number (1, 2, etc) and the last command just shifts today's date by that amount.

When I use the following code to upload to google calendar I get an error:

```<code>def myconverter(o):
    '''
    call the __str__ method of the datetime object that will return a string representation of the value
    ___

    shoutout: https://code-maven.com/serialize-datetime-object-as-json-in-python
    '''
    if isinstance(o, datetime.datetime):
        return o.__str__()

def add_to_calendar(df, calendar_id):
    """Shows basic usage of the Google Calendar API.
    Prints the start and name of the next 10 events on the user's calendar.
    """
    creds = None
    # The file token.pickle stores the user's access and refresh tokens, and is
    # created automatically when the authorization flow completes for the first
    # time.
    if os.path.exists('token.pickle'):
        with open('token.pickle', 'rb') as token:
            creds = pickle.load(token)
    # If there are no (valid) credentials available, let the user log in.
    if not creds or not creds.valid:
        if creds and creds.expired and creds.refresh_token:
            creds.refresh(Request())
        else:
            flow = InstalledAppFlow.from_client_secrets_file(
                'credentials.json', SCOPES)
            creds = flow.run_local_server(port=0)
        # Save the credentials for the next run
        with open('token.pickle', 'wb') as token:
            pickle.dump(creds, token)

    service = build('calendar', 'v3', credentials=creds)

    # Call the Calendar API
    now = datetime.datetime.utcnow().isoformat() + 'Z' # 'Z' indicates UTC time
    print('Adding meals to calendar')

    for i, r in df.iterrows():
        event = {
        'summary': r.name,
        'description': r.meal_period,
        'start': {
            'date': json.dumps(r.meal_date, default=myconverter),
            'timeZone': 'America/Los_Angeles'
        },
        'end': {
            'date': json.dumps(r.meal_date, default=myconverter),
            'timeZone': 'America/Los_Angeles'
        }
        }
        event = service.events().insert(calendarId=calendar_id, body=event).execute()
</code>```

running this code, I get the following error:

```<code>HttpError: <HttpError 400 when requesting https://www.googleapis.com/calendar/v3/calendars/CALENDAR_ID/events?alt=json returned "Invalid value for: Invalid format: ""2020-05-28 22:28:01.204464+00:00""">
</code>```

where CALENDAR_ID is my google calendar id.

If anyone knows how to fix this date issue using python code, this would be incredibly helpful.

答:
How about this answer?

Modification points:

If you want to use start.date and end.date as the all-day event, the format is required to be yyyy-mm-dd. In this case, timeZone is not required.

If you want to use start.dateTime and end.dateTime as the all-day event, the format is required to be RFC3339. In this case, timeZone is required.

From above situations, when your script is modified, how about the following patterns?

Pattern 1:

In this pattern, start.date and end.date are used. For this, please modify as follows.

From:

```<code>'start': {
    'date': json.dumps(r.meal_date, default=myconverter),
    'timeZone': 'America/Los_Angeles'
},
'end': {
    'date': json.dumps(r.meal_date, default=myconverter),
    'timeZone': 'America/Los_Angeles'
}
</code>```

To:

```<code>'start': {
    'date': 'date': parse(r.meal_date).strftime("%Y-%m-%d"),
},
'end': {
    'date': 'date': parse(r.meal_date).strftime("%Y-%m-%d"),
}
</code>```

Pattern 2:

In this pattern, start.dateTime and end.dateTime are used. For this, please modify as follows.

From:

```<code>'start': {
    'date': json.dumps(r.meal_date, default=myconverter),
    'timeZone': 'America/Los_Angeles'
},
'end': {
    'date': json.dumps(r.meal_date, default=myconverter),
    'timeZone': 'America/Los_Angeles'
}
</code>```

To:

```<code>'start': {
    'dateTime': parse(r.meal_date).isoformat(),
    'timeZone': 'America/Los_Angeles'
},
'end': {
    'dateTime': parse(r.meal_date).isoformat(),
    'timeZone': 'America/Los_Angeles'
}
</code>```

Note:

In this modification, from dateutil.parser import parse is used.

From your script, I couldn't see the scope you are using. So if the error related to the scope occurs, please use https://www.googleapis.com/auth/calendar as the scope. At that time, please delete the file of token.pickle and reauthorize the scope. Please be careful this.

Reference:

Events: insert

Body:
Goal: create a Google Calendar event.

Blocker: the date formatting.

background: I'm trying to create a meal planner that takes recipes from a given database and creates events with their name in a google calendar. The database looks like this:

d = {'recipe_id': ['carrot salad', 'leek fritters'], 'meal_date': ['2020-05-28 22:28:01.204464+00:00', '2020-05-29 22:28:01.204464+00:00']}
df = pd.DataFrame(data=d)

the meal date is a product of two

today_date = datetime.datetime.utcnow().isoformat() + 'Z'
df['menu_date'] = today_date
df['menu_date'] = pd.to_datetime(df['menu_date'])
df['meal_date'] = df['menu_date'] + df['meal'].apply(pd.offsets.Day)

Where 'meal' is just a number (1, 2, etc) and the last command just shifts today's date by that amount.

When I use the following code to upload to google calendar I get an error:

def myconverter(o):
    '''
    call the __str__ method of the datetime object that will return a string representation of the value
    ___

    shoutout: https://code-maven.com/serialize-datetime-object-as-json-in-python
    '''
    if isinstance(o, datetime.datetime):
        return o.__str__()

def add_to_calendar(df, calendar_id):
    """Shows basic usage of the Google Calendar API.
    Prints the start and name of the next 10 events on the user's calendar.
    """
    creds = None
    # The file token.pickle stores the user's access and refresh tokens, and is
    # created automatically when the authorization flow completes for the first
    # time.
    if os.path.exists('token.pickle'):
        with open('token.pickle', 'rb') as token:
            creds = pickle.load(token)
    # If there are no (valid) credentials available, let the user log in.
    if not creds or not creds.valid:
        if creds and creds.expired and creds.refresh_token:
            creds.refresh(Request())
        else:
            flow = InstalledAppFlow.from_client_secrets_file(
                'credentials.json', SCOPES)
            creds = flow.run_local_server(port=0)
        # Save the credentials for the next run
        with open('token.pickle', 'wb') as token:
            pickle.dump(creds, token)

    service = build('calendar', 'v3', credentials=creds)

    # Call the Calendar API
    now = datetime.datetime.utcnow().isoformat() + 'Z' # 'Z' indicates UTC time
    print('Adding meals to calendar')

    for i, r in df.iterrows():
        event = {
        'summary': r.name,
        'description': r.meal_period,
        'start': {
            'date': json.dumps(r.meal_date, default=myconverter),
            'timeZone': 'America/Los_Angeles'
        },
        'end': {
            'date': json.dumps(r.meal_date, default=myconverter),
            'timeZone': 'America/Los_Angeles'
        }
        }
        event = service.events().insert(calendarId=calendar_id, body=event).execute()

running this code, I get the following error:

HttpError: <HttpError 400 when requesting https://www.googleapis.com/calendar/v3/calendars/CALENDAR_ID/events?alt=json returned "Invalid value for: Invalid format: ""2020-05-28 22:28:01.204464+00:00""">

where CALENDAR_ID is my google calendar id.

If anyone knows how to fix this date issue using python code, this would be incredibly helpful.

Body:
How about this answer?

Modification points:

If you want to use start.date and end.date as the all-day event, the format is required to be yyyy-mm-dd. In this case, timeZone is not required.

If you want to use start.dateTime and end.dateTime as the all-day event, the format is required to be RFC3339. In this case, timeZone is required.

From above situations, when your script is modified, how about the following patterns?

Pattern 1:

In this pattern, start.date and end.date are used. For this, please modify as follows.

From:

'start': {
    'date': json.dumps(r.meal_date, default=myconverter),
    'timeZone': 'America/Los_Angeles'
},
'end': {
    'date': json.dumps(r.meal_date, default=myconverter),
    'timeZone': 'America/Los_Angeles'
}

To:

'start': {
    'date': 'date': parse(r.meal_date).strftime("%Y-%m-%d"),
},
'end': {
    'date': 'date': parse(r.meal_date).strftime("%Y-%m-%d"),
}

Pattern 2:

In this pattern, start.dateTime and end.dateTime are used. For this, please modify as follows.

From:

'start': {
    'date': json.dumps(r.meal_date, default=myconverter),
    'timeZone': 'America/Los_Angeles'
},
'end': {
    'date': json.dumps(r.meal_date, default=myconverter),
    'timeZone': 'America/Los_Angeles'
}

To:

'start': {
    'dateTime': parse(r.meal_date).isoformat(),
    'timeZone': 'America/Los_Angeles'
},
'end': {
    'dateTime': parse(r.meal_date).isoformat(),
    'timeZone': 'America/Los_Angeles'
}

Note:

In this modification, from dateutil.parser import parse is used.

From your script, I couldn't see the scope you are using. So if the error related to the scope occurs, please use https://www.googleapis.com/auth/calendar as the scope. At that time, please delete the file of token.pickle and reauthorize the scope. Please be careful this.

Reference:

Events: insert


问:
How to implement CRC-10 algorithm
I'm trying to implement a 10-bit CRC with a polynomial of 0x633. I've scoured through countless pages but not much is written on CRC-10.

I've written some sample code that seems to calculate it just fine. I can run some test data through to get a CRC then run the data + CRC back through to get 0, which is expect. The problem is that we're testing it against this calculator and getting incongruent results: http://www.ghsi.de/pages/subpages/Online%20CRC%20Calculation/indexDetails.php?Polynom=11000110011&Message=1f+ff+30+04+05+34+a7. This includes the poly and test data. The result from this calculator is "0x10e" while mine is "0x3b1".

Here is the code, modified from https://cs.fit.edu/code/svn/cse2410f13team7/wireshark/wsutil/crc10.c:

```<code>#include <stdio.h>
#include <stdint.h>

uint16_t GetCRC10(uint16_t crc10, const uint8_t *data_blk_ptr, int data_blk_size);

static const uint16_t byte_crc10_table[256] = {
    0x0000, 0x0233, 0x0255, 0x0066, 0x0299, 0x00aa, 0x00cc, 0x02ff,
    0x0301, 0x0132, 0x0154, 0x0367, 0x0198, 0x03ab, 0x03cd, 0x01fe,
    0x0031, 0x0202, 0x0264, 0x0057, 0x02a8, 0x009b, 0x00fd, 0x02ce,
    0x0330, 0x0103, 0x0165, 0x0356, 0x01a9, 0x039a, 0x03fc, 0x01cf,
    0x0062, 0x0251, 0x0237, 0x0004, 0x02fb, 0x00c8, 0x00ae, 0x029d,
    0x0363, 0x0150, 0x0136, 0x0305, 0x01fa, 0x03c9, 0x03af, 0x019c,
    0x0053, 0x0260, 0x0206, 0x0035, 0x02ca, 0x00f9, 0x009f, 0x02ac,
    0x0352, 0x0161, 0x0107, 0x0334, 0x01cb, 0x03f8, 0x039e, 0x01ad,
    0x00c4, 0x02f7, 0x0291, 0x00a2, 0x025d, 0x006e, 0x0008, 0x023b,
    0x03c5, 0x01f6, 0x0190, 0x03a3, 0x015c, 0x036f, 0x0309, 0x013a,
    0x00f5, 0x02c6, 0x02a0, 0x0093, 0x026c, 0x005f, 0x0039, 0x020a,
    0x03f4, 0x01c7, 0x01a1, 0x0392, 0x016d, 0x035e, 0x0338, 0x010b,
    0x00a6, 0x0295, 0x02f3, 0x00c0, 0x023f, 0x000c, 0x006a, 0x0259,
    0x03a7, 0x0194, 0x01f2, 0x03c1, 0x013e, 0x030d, 0x036b, 0x0158,
    0x0097, 0x02a4, 0x02c2, 0x00f1, 0x020e, 0x003d, 0x005b, 0x0268,
    0x0396, 0x01a5, 0x01c3, 0x03f0, 0x010f, 0x033c, 0x035a, 0x0169,
    0x0188, 0x03bb, 0x03dd, 0x01ee, 0x0311, 0x0122, 0x0144, 0x0377,
    0x0289, 0x00ba, 0x00dc, 0x02ef, 0x0010, 0x0223, 0x0245, 0x0076,
    0x01b9, 0x038a, 0x03ec, 0x01df, 0x0320, 0x0113, 0x0175, 0x0346,
    0x02b8, 0x008b, 0x00ed, 0x02de, 0x0021, 0x0212, 0x0274, 0x0047,
    0x01ea, 0x03d9, 0x03bf, 0x018c, 0x0373, 0x0140, 0x0126, 0x0315,
    0x02eb, 0x00d8, 0x00be, 0x028d, 0x0072, 0x0241, 0x0227, 0x0014,
    0x01db, 0x03e8, 0x038e, 0x01bd, 0x0342, 0x0171, 0x0117, 0x0324,
    0x02da, 0x00e9, 0x008f, 0x02bc, 0x0043, 0x0270, 0x0216, 0x0025,
    0x014c, 0x037f, 0x0319, 0x012a, 0x03d5, 0x01e6, 0x0180, 0x03b3,
    0x024d, 0x007e, 0x0018, 0x022b, 0x00d4, 0x02e7, 0x0281, 0x00b2,
    0x017d, 0x034e, 0x0328, 0x011b, 0x03e4, 0x01d7, 0x01b1, 0x0382,
    0x027c, 0x004f, 0x0029, 0x021a, 0x00e5, 0x02d6, 0x02b0, 0x0083,
    0x012e, 0x031d, 0x037b, 0x0148, 0x03b7, 0x0184, 0x01e2, 0x03d1,
    0x022f, 0x001c, 0x007a, 0x0249, 0x00b6, 0x0285, 0x02e3, 0x00d0,
    0x011f, 0x032c, 0x034a, 0x0179, 0x0386, 0x01b5, 0x01d3, 0x03e0,
    0x021e, 0x002d, 0x004b, 0x0278, 0x0087, 0x02b4, 0x02d2, 0x00e1
};

/* update the data block's CRC-10 remainder one byte at a time */
uint16_t GetCRC10(uint16_t crc10, const uint8_t *data_blk_ptr, int data_blk_size)
{
    register int i;
    uint16_t crc10_accum = 0;

    for (i = 0;  i < data_blk_size; i++) {
        crc10_accum = ((crc10_accum << 8) & 0x3ff)
        ^ byte_crc10_table[( crc10_accum >> 2) & 0xff]
        ^ *data_blk_ptr++;
    }
    crc10_accum = ((crc10_accum << 8) & 0x3ff)
        ^ byte_crc10_table[( crc10_accum >> 2) & 0xff]
        ^ (crc10>>2);
    crc10_accum = ((crc10_accum << 8) & 0x3ff)
        ^ byte_crc10_table[( crc10_accum >> 2) & 0xff]
        ^ ((crc10<<6) & 0xFF);

    return crc10_accum;
}

#define TEST_DATA_SIZE    9

void main()
{
  uint8_t test_input_data[TEST_DATA_SIZE] = {0x1f, 0xff, 0x30, 0x4, 0x5, 0x34, 0xa7, 0x0, 0x0};
  uint16_t crc;
  uint16_t crc_final;

  GenerateCRC10Table();
  crc = GetCRC10(0, test_input_data, TEST_DATA_SIZE-2);
  test_input_data[TEST_DATA_SIZE-2] ^= crc >> 8;
  test_input_data[TEST_DATA_SIZE-1] ^= crc & 0xFF;

  printf("%x\n", crc); // Error here. This crc doesn't match with the calculator.

  crc_final = GetCRC10(0, test_input_data, TEST_DATA_SIZE);

  if (crc_final == 0)
  {
    printf("Success");
  }
}
</code>```

This is the function used to produce the lookup table:

```<code>#define POLYNOMIAL 0x633

static uint16_t byte_crc10_table[256];

void gen_byte_crc10_table(void)
/* generate the table of CRC-10 remainders for all possible bytes */
{
    register int i, j;
    register unsigned short crc10_accum;

    for ( i = 0;  i < 256;  i++ )
    {
        crc10_accum = ((unsigned short) i << 2);
        for ( j = 0;  j < 8;  j++ )
        {
            if ((crc10_accum <<= 1) & 0x400) crc10_accum ^= POLYNOMIAL;
        }
        byte_crc10_table[i] = crc10_accum;
    }
    return;
}
</code>```

I've tried this with the 0x233 normal polynomial form as well.

Is this even possible? In essence, I'm tying to bitwise operations on a complete array of bytes. I suspect the problem is that the calculator does it bit-by-bit and mine is byte-by-byte. Since the poly is 10 bits wide, it doesn't work cleanly with uint8s. I'd really appreciate some feedback. Thanks.

Does it make sense that the calculator CRC and my CRC are different because of the 10 bit polynomial and 8 bit data difference?

答:
A CRC is not defined only by a length and a polynomial. There is also the bit ordering of the incoming bytes, the bit-ordering of the application of the polynomial, the bit as well as byte ordering of the result, the initialization of the CRC, and the final exclusive-or.

That online calculator makes some arbitrary choices in the CRC it calculates, as it itself notes at the top of the page: "Be careful: there are several ways to realize a CRC. They differ (at least) in the way which bit is shifted in first and also in the initialization of the flipflops." It chooses no bit reflections, a zero initialization, and a zero final exclusive-or.

The resulting CRC, with the polynomial you provided, 0x233, actually has a name and an application. It is a CRC-10/ATM (see link). Here is a simple bit-wise implementation:

```<code>unsigned crc10atm_bit(unsigned crc, void const *mem, size_t len) {
    unsigned char const *data = mem;
    if (data == NULL)
        return 0;
    while (len--) {
        crc ^= (unsigned)(*data++) << 2;
        for (unsigned k = 0; k < 8; k++)
            crc = crc & 0x200 ? (crc << 1) ^ 0x233 : crc << 1;
    }
    crc &= 0x3ff;
    return crc;
}
</code>```

The routine uses the convention that the initial value for the CRC is returned when a NULL pointer is passed.

Here is a faster byte-wise implementation using a pre-computed table:

```<code>static unsigned short const table_byte[] = {
    0x000, 0x233, 0x255, 0x066, 0x299, 0x0aa, 0x0cc, 0x2ff, 0x301, 0x132, 0x154,
    0x367, 0x198, 0x3ab, 0x3cd, 0x1fe, 0x031, 0x202, 0x264, 0x057, 0x2a8, 0x09b,
    0x0fd, 0x2ce, 0x330, 0x103, 0x165, 0x356, 0x1a9, 0x39a, 0x3fc, 0x1cf, 0x062,
    0x251, 0x237, 0x004, 0x2fb, 0x0c8, 0x0ae, 0x29d, 0x363, 0x150, 0x136, 0x305,
    0x1fa, 0x3c9, 0x3af, 0x19c, 0x053, 0x260, 0x206, 0x035, 0x2ca, 0x0f9, 0x09f,
    0x2ac, 0x352, 0x161, 0x107, 0x334, 0x1cb, 0x3f8, 0x39e, 0x1ad, 0x0c4, 0x2f7,
    0x291, 0x0a2, 0x25d, 0x06e, 0x008, 0x23b, 0x3c5, 0x1f6, 0x190, 0x3a3, 0x15c,
    0x36f, 0x309, 0x13a, 0x0f5, 0x2c6, 0x2a0, 0x093, 0x26c, 0x05f, 0x039, 0x20a,
    0x3f4, 0x1c7, 0x1a1, 0x392, 0x16d, 0x35e, 0x338, 0x10b, 0x0a6, 0x295, 0x2f3,
    0x0c0, 0x23f, 0x00c, 0x06a, 0x259, 0x3a7, 0x194, 0x1f2, 0x3c1, 0x13e, 0x30d,
    0x36b, 0x158, 0x097, 0x2a4, 0x2c2, 0x0f1, 0x20e, 0x03d, 0x05b, 0x268, 0x396,
    0x1a5, 0x1c3, 0x3f0, 0x10f, 0x33c, 0x35a, 0x169, 0x188, 0x3bb, 0x3dd, 0x1ee,
    0x311, 0x122, 0x144, 0x377, 0x289, 0x0ba, 0x0dc, 0x2ef, 0x010, 0x223, 0x245,
    0x076, 0x1b9, 0x38a, 0x3ec, 0x1df, 0x320, 0x113, 0x175, 0x346, 0x2b8, 0x08b,
    0x0ed, 0x2de, 0x021, 0x212, 0x274, 0x047, 0x1ea, 0x3d9, 0x3bf, 0x18c, 0x373,
    0x140, 0x126, 0x315, 0x2eb, 0x0d8, 0x0be, 0x28d, 0x072, 0x241, 0x227, 0x014,
    0x1db, 0x3e8, 0x38e, 0x1bd, 0x342, 0x171, 0x117, 0x324, 0x2da, 0x0e9, 0x08f,
    0x2bc, 0x043, 0x270, 0x216, 0x025, 0x14c, 0x37f, 0x319, 0x12a, 0x3d5, 0x1e6,
    0x180, 0x3b3, 0x24d, 0x07e, 0x018, 0x22b, 0x0d4, 0x2e7, 0x281, 0x0b2, 0x17d,
    0x34e, 0x328, 0x11b, 0x3e4, 0x1d7, 0x1b1, 0x382, 0x27c, 0x04f, 0x029, 0x21a,
    0x0e5, 0x2d6, 0x2b0, 0x083, 0x12e, 0x31d, 0x37b, 0x148, 0x3b7, 0x184, 0x1e2,
    0x3d1, 0x22f, 0x01c, 0x07a, 0x249, 0x0b6, 0x285, 0x2e3, 0x0d0, 0x11f, 0x32c,
    0x34a, 0x179, 0x386, 0x1b5, 0x1d3, 0x3e0, 0x21e, 0x02d, 0x04b, 0x278, 0x087,
    0x2b4, 0x2d2, 0x0e1
};

unsigned crc10atm_byte(unsigned crc, void const *mem, size_t len) {
    unsigned char const *data = mem;
    if (data == NULL)
        return 0;
    while (len--)
        crc = (crc << 8) ^
              table_byte[((crc >> 2) ^ *data++) & 0xff];
    crc &= 0x3ff;
    return crc;
}
</code>```

You might prefer different choices, e.g. an initial value of 0x3ff and a final exclusive-or of that same value. That would avoid strings of any number of zeros having a CRC of zero. Also some shifts can be avoided if reflections are used.

Title: How to implement CRC-10 algorithm

Body:
I'm trying to implement a 10-bit CRC with a polynomial of 0x633. I've scoured through countless pages but not much is written on CRC-10.

I've written some sample code that seems to calculate it just fine. I can run some test data through to get a CRC then run the data + CRC back through to get 0, which is expect. The problem is that we're testing it against this calculator and getting incongruent results: http://www.ghsi.de/pages/subpages/Online%20CRC%20Calculation/indexDetails.php?Polynom=11000110011&Message=1f+ff+30+04+05+34+a7. This includes the poly and test data. The result from this calculator is "0x10e" while mine is "0x3b1".

Here is the code, modified from https://cs.fit.edu/code/svn/cse2410f13team7/wireshark/wsutil/crc10.c:

#include <stdio.h>
#include <stdint.h>

uint16_t GetCRC10(uint16_t crc10, const uint8_t *data_blk_ptr, int data_blk_size);

static const uint16_t byte_crc10_table[256] = {
    0x0000, 0x0233, 0x0255, 0x0066, 0x0299, 0x00aa, 0x00cc, 0x02ff,
    0x0301, 0x0132, 0x0154, 0x0367, 0x0198, 0x03ab, 0x03cd, 0x01fe,
    0x0031, 0x0202, 0x0264, 0x0057, 0x02a8, 0x009b, 0x00fd, 0x02ce,
    0x0330, 0x0103, 0x0165, 0x0356, 0x01a9, 0x039a, 0x03fc, 0x01cf,
    0x0062, 0x0251, 0x0237, 0x0004, 0x02fb, 0x00c8, 0x00ae, 0x029d,
    0x0363, 0x0150, 0x0136, 0x0305, 0x01fa, 0x03c9, 0x03af, 0x019c,
    0x0053, 0x0260, 0x0206, 0x0035, 0x02ca, 0x00f9, 0x009f, 0x02ac,
    0x0352, 0x0161, 0x0107, 0x0334, 0x01cb, 0x03f8, 0x039e, 0x01ad,
    0x00c4, 0x02f7, 0x0291, 0x00a2, 0x025d, 0x006e, 0x0008, 0x023b,
    0x03c5, 0x01f6, 0x0190, 0x03a3, 0x015c, 0x036f, 0x0309, 0x013a,
    0x00f5, 0x02c6, 0x02a0, 0x0093, 0x026c, 0x005f, 0x0039, 0x020a,
    0x03f4, 0x01c7, 0x01a1, 0x0392, 0x016d, 0x035e, 0x0338, 0x010b,
    0x00a6, 0x0295, 0x02f3, 0x00c0, 0x023f, 0x000c, 0x006a, 0x0259,
    0x03a7, 0x0194, 0x01f2, 0x03c1, 0x013e, 0x030d, 0x036b, 0x0158,
    0x0097, 0x02a4, 0x02c2, 0x00f1, 0x020e, 0x003d, 0x005b, 0x0268,
    0x0396, 0x01a5, 0x01c3, 0x03f0, 0x010f, 0x033c, 0x035a, 0x0169,
    0x0188, 0x03bb, 0x03dd, 0x01ee, 0x0311, 0x0122, 0x0144, 0x0377,
    0x0289, 0x00ba, 0x00dc, 0x02ef, 0x0010, 0x0223, 0x0245, 0x0076,
    0x01b9, 0x038a, 0x03ec, 0x01df, 0x0320, 0x0113, 0x0175, 0x0346,
    0x02b8, 0x008b, 0x00ed, 0x02de, 0x0021, 0x0212, 0x0274, 0x0047,
    0x01ea, 0x03d9, 0x03bf, 0x018c, 0x0373, 0x0140, 0x0126, 0x0315,
    0x02eb, 0x00d8, 0x00be, 0x028d, 0x0072, 0x0241, 0x0227, 0x0014,
    0x01db, 0x03e8, 0x038e, 0x01bd, 0x0342, 0x0171, 0x0117, 0x0324,
    0x02da, 0x00e9, 0x008f, 0x02bc, 0x0043, 0x0270, 0x0216, 0x0025,
    0x014c, 0x037f, 0x0319, 0x012a, 0x03d5, 0x01e6, 0x0180, 0x03b3,
    0x024d, 0x007e, 0x0018, 0x022b, 0x00d4, 0x02e7, 0x0281, 0x00b2,
    0x017d, 0x034e, 0x0328, 0x011b, 0x03e4, 0x01d7, 0x01b1, 0x0382,
    0x027c, 0x004f, 0x0029, 0x021a, 0x00e5, 0x02d6, 0x02b0, 0x0083,
    0x012e, 0x031d, 0x037b, 0x0148, 0x03b7, 0x0184, 0x01e2, 0x03d1,
    0x022f, 0x001c, 0x007a, 0x0249, 0x00b6, 0x0285, 0x02e3, 0x00d0,
    0x011f, 0x032c, 0x034a, 0x0179, 0x0386, 0x01b5, 0x01d3, 0x03e0,
    0x021e, 0x002d, 0x004b, 0x0278, 0x0087, 0x02b4, 0x02d2, 0x00e1
};

/* update the data block's CRC-10 remainder one byte at a time */
uint16_t GetCRC10(uint16_t crc10, const uint8_t *data_blk_ptr, int data_blk_size)
{
    register int i;
    uint16_t crc10_accum = 0;

    for (i = 0;  i < data_blk_size; i++) {
        crc10_accum = ((crc10_accum << 8) & 0x3ff)
        ^ byte_crc10_table[( crc10_accum >> 2) & 0xff]
        ^ *data_blk_ptr++;
    }
    crc10_accum = ((crc10_accum << 8) & 0x3ff)
        ^ byte_crc10_table[( crc10_accum >> 2) & 0xff]
        ^ (crc10>>2);
    crc10_accum = ((crc10_accum << 8) & 0x3ff)
        ^ byte_crc10_table[( crc10_accum >> 2) & 0xff]
        ^ ((crc10<<6) & 0xFF);

    return crc10_accum;
}

#define TEST_DATA_SIZE    9

void main()
{
  uint8_t test_input_data[TEST_DATA_SIZE] = {0x1f, 0xff, 0x30, 0x4, 0x5, 0x34, 0xa7, 0x0, 0x0};
  uint16_t crc;
  uint16_t crc_final;

  GenerateCRC10Table();
  crc = GetCRC10(0, test_input_data, TEST_DATA_SIZE-2);
  test_input_data[TEST_DATA_SIZE-2] ^= crc >> 8;
  test_input_data[TEST_DATA_SIZE-1] ^= crc & 0xFF;

  printf("%x\n", crc); // Error here. This crc doesn't match with the calculator.

  crc_final = GetCRC10(0, test_input_data, TEST_DATA_SIZE);

  if (crc_final == 0)
  {
    printf("Success");
  }
}

This is the function used to produce the lookup table:

#define POLYNOMIAL 0x633

static uint16_t byte_crc10_table[256];

void gen_byte_crc10_table(void)
/* generate the table of CRC-10 remainders for all possible bytes */
{
    register int i, j;
    register unsigned short crc10_accum;

    for ( i = 0;  i < 256;  i++ )
    {
        crc10_accum = ((unsigned short) i << 2);
        for ( j = 0;  j < 8;  j++ )
        {
            if ((crc10_accum <<= 1) & 0x400) crc10_accum ^= POLYNOMIAL;
        }
        byte_crc10_table[i] = crc10_accum;
    }
    return;
}

I've tried this with the 0x233 normal polynomial form as well.

Is this even possible? In essence, I'm tying to bitwise operations on a complete array of bytes. I suspect the problem is that the calculator does it bit-by-bit and mine is byte-by-byte. Since the poly is 10 bits wide, it doesn't work cleanly with uint8s. I'd really appreciate some feedback. Thanks.

Does it make sense that the calculator CRC and my CRC are different because of the 10 bit polynomial and 8 bit data difference?

Body:
A CRC is not defined only by a length and a polynomial. There is also the bit ordering of the incoming bytes, the bit-ordering of the application of the polynomial, the bit as well as byte ordering of the result, the initialization of the CRC, and the final exclusive-or.

That online calculator makes some arbitrary choices in the CRC it calculates, as it itself notes at the top of the page: "Be careful: there are several ways to realize a CRC. They differ (at least) in the way which bit is shifted in first and also in the initialization of the flipflops." It chooses no bit reflections, a zero initialization, and a zero final exclusive-or.

The resulting CRC, with the polynomial you provided, 0x233, actually has a name and an application. It is a CRC-10/ATM (see link). Here is a simple bit-wise implementation:

unsigned crc10atm_bit(unsigned crc, void const *mem, size_t len) {
    unsigned char const *data = mem;
    if (data == NULL)
        return 0;
    while (len--) {
        crc ^= (unsigned)(*data++) << 2;
        for (unsigned k = 0; k < 8; k++)
            crc = crc & 0x200 ? (crc << 1) ^ 0x233 : crc << 1;
    }
    crc &= 0x3ff;
    return crc;
}

The routine uses the convention that the initial value for the CRC is returned when a NULL pointer is passed.

Here is a faster byte-wise implementation using a pre-computed table:

static unsigned short const table_byte[] = {
    0x000, 0x233, 0x255, 0x066, 0x299, 0x0aa, 0x0cc, 0x2ff, 0x301, 0x132, 0x154,
    0x367, 0x198, 0x3ab, 0x3cd, 0x1fe, 0x031, 0x202, 0x264, 0x057, 0x2a8, 0x09b,
    0x0fd, 0x2ce, 0x330, 0x103, 0x165, 0x356, 0x1a9, 0x39a, 0x3fc, 0x1cf, 0x062,
    0x251, 0x237, 0x004, 0x2fb, 0x0c8, 0x0ae, 0x29d, 0x363, 0x150, 0x136, 0x305,
    0x1fa, 0x3c9, 0x3af, 0x19c, 0x053, 0x260, 0x206, 0x035, 0x2ca, 0x0f9, 0x09f,
    0x2ac, 0x352, 0x161, 0x107, 0x334, 0x1cb, 0x3f8, 0x39e, 0x1ad, 0x0c4, 0x2f7,
    0x291, 0x0a2, 0x25d, 0x06e, 0x008, 0x23b, 0x3c5, 0x1f6, 0x190, 0x3a3, 0x15c,
    0x36f, 0x309, 0x13a, 0x0f5, 0x2c6, 0x2a0, 0x093, 0x26c, 0x05f, 0x039, 0x20a,
    0x3f4, 0x1c7, 0x1a1, 0x392, 0x16d, 0x35e, 0x338, 0x10b, 0x0a6, 0x295, 0x2f3,
    0x0c0, 0x23f, 0x00c, 0x06a, 0x259, 0x3a7, 0x194, 0x1f2, 0x3c1, 0x13e, 0x30d,
    0x36b, 0x158, 0x097, 0x2a4, 0x2c2, 0x0f1, 0x20e, 0x03d, 0x05b, 0x268, 0x396,
    0x1a5, 0x1c3, 0x3f0, 0x10f, 0x33c, 0x35a, 0x169, 0x188, 0x3bb, 0x3dd, 0x1ee,
    0x311, 0x122, 0x144, 0x377, 0x289, 0x0ba, 0x0dc, 0x2ef, 0x010, 0x223, 0x245,
    0x076, 0x1b9, 0x38a, 0x3ec, 0x1df, 0x320, 0x113, 0x175, 0x346, 0x2b8, 0x08b,
    0x0ed, 0x2de, 0x021, 0x212, 0x274, 0x047, 0x1ea, 0x3d9, 0x3bf, 0x18c, 0x373,
    0x140, 0x126, 0x315, 0x2eb, 0x0d8, 0x0be, 0x28d, 0x072, 0x241, 0x227, 0x014,
    0x1db, 0x3e8, 0x38e, 0x1bd, 0x342, 0x171, 0x117, 0x324, 0x2da, 0x0e9, 0x08f,
    0x2bc, 0x043, 0x270, 0x216, 0x025, 0x14c, 0x37f, 0x319, 0x12a, 0x3d5, 0x1e6,
    0x180, 0x3b3, 0x24d, 0x07e, 0x018, 0x22b, 0x0d4, 0x2e7, 0x281, 0x0b2, 0x17d,
    0x34e, 0x328, 0x11b, 0x3e4, 0x1d7, 0x1b1, 0x382, 0x27c, 0x04f, 0x029, 0x21a,
    0x0e5, 0x2d6, 0x2b0, 0x083, 0x12e, 0x31d, 0x37b, 0x148, 0x3b7, 0x184, 0x1e2,
    0x3d1, 0x22f, 0x01c, 0x07a, 0x249, 0x0b6, 0x285, 0x2e3, 0x0d0, 0x11f, 0x32c,
    0x34a, 0x179, 0x386, 0x1b5, 0x1d3, 0x3e0, 0x21e, 0x02d, 0x04b, 0x278, 0x087,
    0x2b4, 0x2d2, 0x0e1
};

unsigned crc10atm_byte(unsigned crc, void const *mem, size_t len) {
    unsigned char const *data = mem;
    if (data == NULL)
        return 0;
    while (len--)
        crc = (crc << 8) ^
              table_byte[((crc >> 2) ^ *data++) & 0xff];
    crc &= 0x3ff;
    return crc;
}

You might prefer different choices, e.g. an initial value of 0x3ff and a final exclusive-or of that same value. That would avoid strings of any number of zeros having a CRC of zero. Also some shifts can be avoided if reflections are used.


问:
How do you change column names to lowercase with linux and store the file as it is?
I am trying to change the column names to lowercase in a csv file. I found the code to do that online but I dont know how to replace the old column names(uppercase) with new column names(lowercase) in the original file. I did something like this:
$cat head -n1 xxx.csv | tr "[A-Z]" "[a-z]"

But it simply just prints out the column names in lowercase, which is not enough for me.
I tried to add sed -i but it did not do any good. Thanks!!

答:
You can use sed to tell it to replace the first line with all lower-case and then print the rest as-is:

```<code>sed '1s/.*/\L&/' ./xxx.csv
</code>```

Redirect the output or use -i to do an in-place edit.

Proof of Concept

```<code>$ echo -e "COL1,COL2,COL3\nFoO,bAr,baZ" | sed '1s/.*/\L&/'
col1,col2,col3
FoO,bAr,baZ
</code>```

Body:
You can use sed to tell it to replace the first line with all lower-case and then print the rest as-is:

sed '1s/.*/\L&/' ./xxx.csv

Redirect the output or use -i to do an in-place edit.

Proof of Concept

$ echo -e "COL1,COL2,COL3\nFoO,bAr,baZ" | sed '1s/.*/\L&/'
col1,col2,col3
FoO,bAr,baZ


问:
group list of dict by tuple value
I tried to solve this with list comprehension, itemgetter and groupby but I don't seem close.  Given this type of list of dict:

```<code>test_list = [{'text': "Hi",'bbox': (0,0)},
          {'text': "There.",'bbox': (1,0)},
          {'text': "Im",'bbox': (0,1)},
          {'text': "John.",'bbox': (1,1)},
         ]
</code>```

I am looking for this result:

```<code>[['Hi',"There."],['Im','John.']]
</code>```

Where the 'text' values are grouped by the second tuple element in the 'bbox'.  Thanks

答:
A groupby approach. One line but not particularly readable.

```<code>from itertools import groupby

test_list = [
    {'text': "Hi",'bbox': (0,0)},
    {'text': "There.",'bbox': (1,0)},
    {'text': "Im",'bbox': (0,1)},
    {'text': "John.",'bbox': (1,1)},
]

result = [[s['text'] for s in groups] for _, groups in groupby(test_list, key=lambda x: x['bbox'][1])]

print(result)
</code>```

Note this happens to work because the input is sorted appropriately already, but if it wasn't, it would need to be sorted first before calling groupby.

Title: group list of dict by tuple value

Body:
I tried to solve this with list comprehension, itemgetter and groupby but I don't seem close.  Given this type of list of dict:

test_list = [{'text': "Hi",'bbox': (0,0)},
          {'text': "There.",'bbox': (1,0)},
          {'text': "Im",'bbox': (0,1)},
          {'text': "John.",'bbox': (1,1)},
         ]

I am looking for this result:

[['Hi',"There."],['Im','John.']]

Where the 'text' values are grouped by the second tuple element in the 'bbox'.  Thanks

Body:
A groupby approach. One line but not particularly readable.

from itertools import groupby

test_list = [
    {'text': "Hi",'bbox': (0,0)},
    {'text': "There.",'bbox': (1,0)},
    {'text': "Im",'bbox': (0,1)},
    {'text': "John.",'bbox': (1,1)},
]

result = [[s['text'] for s in groups] for _, groups in groupby(test_list, key=lambda x: x['bbox'][1])]

print(result)

Note this happens to work because the input is sorted appropriately already, but if it wasn't, it would need to be sorted first before calling groupby.