问:
Why did this reselect selector cause a re-render?
One of my components was re-rendering, and I realised it was because of the allPageViews selector below:

```<code>const getPages = (state: IAppState) => {
  return state.pages;
};

export const attachPageViews = createSelector(
  getPages,
  (pages) => pages.pageViews
);
export const selectPageViews = createSelector(
  attachPageViews,
  (pageViews) => pageViews
);

export const allPageViews = createSelector(
  selectPageViews,
  (pageStore: PageViewStore) => {
    let returnedPageViews: PageView[] = [];
    for (const section of Object.values(pageStore.sections)) {
      for (const page of Object.values(section!.pageViews)) {
        returnedPageViews = [...returnedPageViews, page!];
      }
    }
    return returnedPageViews;
  }
);
</code>```

When I was dispatching an action I was changing the pages reducer, but not the pageViews contained inside (pages have another key called data that I was updating). So by my understanding selectPageViews should not change (because the underlying pageViews are not changing) and so allPageViews should just be memoizing and not re-calculating because nothing has been updated.

Nonetheless, it was re-calculating. When I moved the returnedPageViews array and the for loops into the component that was using useSelector() then the component stopped re-rendering.

So my question is - how is Reselect working, and why did it re-calculate and trigger the re-render when the array was being made in allPageViews?

答:
I was changing the pages reducer, but not the pageViews contained inside (pages has another key called data that I was updating). So by my understanding selectPageViews should not change (because the underlying pageViews are not changing) and so allPageViews should just be memoising and not re-calculating because nothing has been updated.

That is correct, state.page.pageViews did not change so selectPageViews will return memoized result and so will allPageViews.

Nonetheless it was re-calculating. When I moved the returnedPageViews array and the for loops into the component that was using useSelector() then the component stopped re-rendering. So my question is - how is Reselect working, and why did it re-calculate and trigger the re-render when the array was being made in allPageViews?

That makes no sense, so the selector is not is triggering re rendering? And Nonetheless it was re-calculating is not true, here is your code below demonstrating that your initial assumption was correct; if you don't change state.page.pageViews then both selectPageViews and allPageViews will return their memoized result (will not re calculate):

const { createSelector } = Reselect;
const getPages = (state) => {
  return state.pages;
};

const attachPageViews = createSelector(
  getPages,
  (pages) => pages.pageViews
);
//this one is kind of useless, it does x=>x so you may as
//  well do: const selectPageViews = attachPageViews
const selectPageViews = createSelector(
  attachPageViews,
  (pageViews) => {
    console.log(
      'selectPageViews logs once but is called twice'
    );
    return pageViews;
  }
);

const allPageViews = createSelector(
  selectPageViews,
  (pageStore) => {
    console.log(
      'allPageViews logs once but is called twice'
    );
    return { new: 'object', pageStore };
  }
);
const state = {
  pages: {
    pageViews: { value: 'this is page views' },
  },
};
console.log('calling allPageViews first time');
const one = allPageViews(state);
console.log('calling allPageViews second time with changed state.pages');
const two = allPageViews({
  ...state,
  pages: {
    ...state.pages,
    changedSomething: true,
  },
});
console.log('both results are the same:',one === two);```
<pre class="snippet-code-html lang-html prettyprint-override"><code><script src="https://cdnjs.cloudflare.com/ajax/libs/reselect/4.0.0/reselect.min.js"></script>

<div id="root"></div></code>```

Body:
One of my components was re-rendering, and I realised it was because of the allPageViews selector below:

const getPages = (state: IAppState) => {
  return state.pages;
};

export const attachPageViews = createSelector(
  getPages,
  (pages) => pages.pageViews
);
export const selectPageViews = createSelector(
  attachPageViews,
  (pageViews) => pageViews
);

export const allPageViews = createSelector(
  selectPageViews,
  (pageStore: PageViewStore) => {
    let returnedPageViews: PageView[] = [];
    for (const section of Object.values(pageStore.sections)) {
      for (const page of Object.values(section!.pageViews)) {
        returnedPageViews = [...returnedPageViews, page!];
      }
    }
    return returnedPageViews;
  }
);

When I was dispatching an action I was changing the pages reducer, but not the pageViews contained inside (pages have another key called data that I was updating). So by my understanding selectPageViews should not change (because the underlying pageViews are not changing) and so allPageViews should just be memoizing and not re-calculating because nothing has been updated.

Nonetheless, it was re-calculating. When I moved the returnedPageViews array and the for loops into the component that was using useSelector() then the component stopped re-rendering.

So my question is - how is Reselect working, and why did it re-calculate and trigger the re-render when the array was being made in allPageViews?

Body:
I was changing the pages reducer, but not the pageViews contained inside (pages has another key called data that I was updating). So by my understanding selectPageViews should not change (because the underlying pageViews are not changing) and so allPageViews should just be memoising and not re-calculating because nothing has been updated.

That is correct, state.page.pageViews did not change so selectPageViews will return memoized result and so will allPageViews.

Nonetheless it was re-calculating. When I moved the returnedPageViews array and the for loops into the component that was using useSelector() then the component stopped re-rendering. So my question is - how is Reselect working, and why did it re-calculate and trigger the re-render when the array was being made in allPageViews?

That makes no sense, so the selector is not is triggering re rendering? And Nonetheless it was re-calculating is not true, here is your code below demonstrating that your initial assumption was correct; if you don't change state.page.pageViews then both selectPageViews and allPageViews will return their memoized result (will not re calculate):

const { createSelector } = Reselect;
const getPages = (state) => {
  return state.pages;
};

const attachPageViews = createSelector(
  getPages,
  (pages) => pages.pageViews
);
//this one is kind of useless, it does x=>x so you may as
//  well do: const selectPageViews = attachPageViews
const selectPageViews = createSelector(
  attachPageViews,
  (pageViews) => {
    console.log(
      'selectPageViews logs once but is called twice'
    );
    return pageViews;
  }
);

const allPageViews = createSelector(
  selectPageViews,
  (pageStore) => {
    console.log(
      'allPageViews logs once but is called twice'
    );
    return { new: 'object', pageStore };
  }
);
const state = {
  pages: {
    pageViews: { value: 'this is page views' },
  },
};
console.log('calling allPageViews first time');
const one = allPageViews(state);
console.log('calling allPageViews second time with changed state.pages');
const two = allPageViews({
  ...state,
  pages: {
    ...state.pages,
    changedSomething: true,
  },
});
console.log('both results are the same:',one === two);

<script src="https://cdnjs.cloudflare.com/ajax/libs/reselect/4.0.0/reselect.min.js"></script>

<div id="root"></div>


来源: stackexchange

问:
CS50 Android Track Filter will not run in device despite building without errors
I am trying to implement the filter function in the Pokedex app, and although the app "Builds" without any errors, when I go to run it within the virtual Android phone, I get the error "Pokedex Keeps Stopping," on the virtual device.  Since my code builds correctly, I cannot really figure out why it would continue to crash on the virtual device.  Any help will be appreciated!

Here is my PokedexAdapter.java file, with the filter function added at the bottom:

```<code>package edu.harvard.cs50.pokedex;

import android.content.Context;
import android.content.Intent;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Filter;
import android.widget.Filterable;
import android.widget.LinearLayout;
import android.widget.TextView;

import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;

import com.android.volley.Request;
import com.android.volley.RequestQueue;
import com.android.volley.Response;
import com.android.volley.VolleyError;
import com.android.volley.toolbox.JsonObjectRequest;
import com.android.volley.toolbox.Volley;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Hashtable;
import java.util.List;

public class PokedexAdapter extends RecyclerView.Adapter<PokedexAdapter.PokedexViewHolder> implements Filterable {

    public static class PokedexViewHolder extends RecyclerView.ViewHolder {
        public LinearLayout containerView;
        public TextView textView;

        PokedexViewHolder(View view) {
            super(view);

            containerView = view.findViewById(R.id.pokedex_row);
            textView = view.findViewById(R.id.pokedex_row_text_view);

            containerView.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    Pokemon current = (Pokemon) containerView.getTag();
                    Intent intent = new Intent(v.getContext(), PokemonActivity.class);
                    intent.putExtra("url", current.getUrl());

                    v.getContext().startActivity(intent);
                }
            });
        }
    }

    private List<Pokemon> pokemon = new ArrayList<>();
    private RequestQueue requestQueue;

    PokedexAdapter(Context context) {
        requestQueue = Volley.newRequestQueue(context);
        loadPokemon();
    }

    public void loadPokemon() {
        String url = "https://pokeapi.co/api/v2/pokemon?limit=151";
        JsonObjectRequest request = new JsonObjectRequest(Request.Method.GET, url, null, new Response.Listener<JSONObject>() {
            @Override
            public void onResponse(JSONObject response) {
                try {
                    JSONArray results = response.getJSONArray("results");
                    for (int i = 0; i < results.length(); i++) {
                        JSONObject result = results.getJSONObject(i);
                        String name = result.getString("name");
                        pokemon.add(new Pokemon(
                            name.substring(0, 1).toUpperCase() + name.substring(1),
                            result.getString("url")
                        ));
                    }

                    notifyDataSetChanged();
                } catch (JSONException e) {
                    Log.e("cs50", "Json error", e);
                }
            }
        }, new Response.ErrorListener() {
            @Override
            public void onErrorResponse(VolleyError error) {
                Log.e("cs50", "Pokemon list error", error);
            }
        });

        requestQueue.add(request);
    }

    @NonNull
    @Override
    public PokedexViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        View view = LayoutInflater.from(parent.getContext())
                .inflate(R.layout.pokedex_row, parent, false);

        return new PokedexViewHolder(view);
    }

    @Override
    public void onBindViewHolder(@NonNull PokedexViewHolder holder, int position) {
        Pokemon current = pokemon.get(position);
        holder.textView.setText(current.getName());
        holder.containerView.setTag(current);
    }

    @Override
    public int getItemCount() {
        return pokemon.size();
    }

    @Override
    public Filter getFilter() {
        return new PokemonFilter();
    }

    private class PokemonFilter extends Filter {
        @Override
        protected FilterResults performFiltering(CharSequence constraint) {
            // implement your search here!
            FilterResults results = new FilterResults();
            if (constraint == null || constraint.length() == 0) {
                //returns whole list if nothing is entered
                results.values = pokemon;
                results.count = pokemon.size();
            }
            else {
                List<Pokemon> filteredPokemon = new ArrayList<>();
                for (Pokemon name : pokemon) {
                    if (name.getName().toUpperCase().startsWith(constraint.toString().toUpperCase())) {
                        filteredPokemon.add(name);
                        results.values = filteredPokemon; // you need to create this variable!
                        results.count = filteredPokemon.size();
                    }
                }
            }
            return results;
        }

        @Override
        protected void publishResults(CharSequence constraint, FilterResults results) {
            List<Pokemon> filtered = (List<Pokemon>) results.values;
            notifyDataSetChanged();
        }
    }
}
</code>```

And here is how it is implemented in MainActivity.java:

```<code>package edu.harvard.cs50.pokedex;

import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;

import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.SearchView;

public class MainActivity extends AppCompatActivity implements SearchView.OnQueryTextListener {
    private RecyclerView recyclerView;
    private PokedexAdapter adapter;  //private RecyclerView.Adapter adapter;
    private RecyclerView.LayoutManager layoutManager;

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

        recyclerView = findViewById(R.id.recycler_view);
        adapter = new PokedexAdapter(getApplicationContext());
        layoutManager = new LinearLayoutManager(this);

        recyclerView.setAdapter(adapter);
        recyclerView.setLayoutManager(layoutManager);
    }
    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.main_menu, menu);
        MenuItem searchItem = menu.findItem(R.id.action_search);
        SearchView searchView = (SearchView) searchItem.getActionView();
        searchView.setOnQueryTextListener(this);

        return true;
    }

    @Override
    public boolean onQueryTextChange(String newText) {
        adapter.getFilter().filter(newText);
        return false;
    }

    @Override
    public boolean onQueryTextSubmit(String newText) {
        adapter.getFilter().filter(newText);
        return false;
    }
}
</code>```

答:
I had a similar issue which was caused by the following :

```<code>@Override
public int getItemCount() {
    return pokemon.size();
}
</code>```

I believe it can happen that pokemon is not initiated and therefore doesn't have a return value (or equals "null")

I added an if statement that would just return 0 if pokemon is null

```<code>@Override
public int getItemCount() {
    if (pokemon != null) {
        return pokemon.size();
    } else {
        return 0;
    }
}
</code>```

I also have changed the variable name pokemon to the variable name of my Array List that holds the filtered items.

ContentLicense: CC BY-SA 4.0

Body:
I am trying to implement the filter function in the Pokedex app, and although the app "Builds" without any errors, when I go to run it within the virtual Android phone, I get the error "Pokedex Keeps Stopping," on the virtual device.  Since my code builds correctly, I cannot really figure out why it would continue to crash on the virtual device.  Any help will be appreciated!

Here is my PokedexAdapter.java file, with the filter function added at the bottom:

package edu.harvard.cs50.pokedex;

import android.content.Context;
import android.content.Intent;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Filter;
import android.widget.Filterable;
import android.widget.LinearLayout;
import android.widget.TextView;

import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;

import com.android.volley.Request;
import com.android.volley.RequestQueue;
import com.android.volley.Response;
import com.android.volley.VolleyError;
import com.android.volley.toolbox.JsonObjectRequest;
import com.android.volley.toolbox.Volley;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Hashtable;
import java.util.List;

public class PokedexAdapter extends RecyclerView.Adapter<PokedexAdapter.PokedexViewHolder> implements Filterable {

    public static class PokedexViewHolder extends RecyclerView.ViewHolder {
        public LinearLayout containerView;
        public TextView textView;

        PokedexViewHolder(View view) {
            super(view);

            containerView = view.findViewById(R.id.pokedex_row);
            textView = view.findViewById(R.id.pokedex_row_text_view);

            containerView.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    Pokemon current = (Pokemon) containerView.getTag();
                    Intent intent = new Intent(v.getContext(), PokemonActivity.class);
                    intent.putExtra("url", current.getUrl());

                    v.getContext().startActivity(intent);
                }
            });
        }
    }

    private List<Pokemon> pokemon = new ArrayList<>();
    private RequestQueue requestQueue;

    PokedexAdapter(Context context) {
        requestQueue = Volley.newRequestQueue(context);
        loadPokemon();
    }

    public void loadPokemon() {
        String url = "https://pokeapi.co/api/v2/pokemon?limit=151";
        JsonObjectRequest request = new JsonObjectRequest(Request.Method.GET, url, null, new Response.Listener<JSONObject>() {
            @Override
            public void onResponse(JSONObject response) {
                try {
                    JSONArray results = response.getJSONArray("results");
                    for (int i = 0; i < results.length(); i++) {
                        JSONObject result = results.getJSONObject(i);
                        String name = result.getString("name");
                        pokemon.add(new Pokemon(
                            name.substring(0, 1).toUpperCase() + name.substring(1),
                            result.getString("url")
                        ));
                    }

                    notifyDataSetChanged();
                } catch (JSONException e) {
                    Log.e("cs50", "Json error", e);
                }
            }
        }, new Response.ErrorListener() {
            @Override
            public void onErrorResponse(VolleyError error) {
                Log.e("cs50", "Pokemon list error", error);
            }
        });

        requestQueue.add(request);
    }

    @NonNull
    @Override
    public PokedexViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        View view = LayoutInflater.from(parent.getContext())
                .inflate(R.layout.pokedex_row, parent, false);

        return new PokedexViewHolder(view);
    }

    @Override
    public void onBindViewHolder(@NonNull PokedexViewHolder holder, int position) {
        Pokemon current = pokemon.get(position);
        holder.textView.setText(current.getName());
        holder.containerView.setTag(current);
    }

    @Override
    public int getItemCount() {
        return pokemon.size();
    }

    @Override
    public Filter getFilter() {
        return new PokemonFilter();
    }

    private class PokemonFilter extends Filter {
        @Override
        protected FilterResults performFiltering(CharSequence constraint) {
            // implement your search here!
            FilterResults results = new FilterResults();
            if (constraint == null || constraint.length() == 0) {
                //returns whole list if nothing is entered
                results.values = pokemon;
                results.count = pokemon.size();
            }
            else {
                List<Pokemon> filteredPokemon = new ArrayList<>();
                for (Pokemon name : pokemon) {
                    if (name.getName().toUpperCase().startsWith(constraint.toString().toUpperCase())) {
                        filteredPokemon.add(name);
                        results.values = filteredPokemon; // you need to create this variable!
                        results.count = filteredPokemon.size();
                    }
                }
            }
            return results;
        }

        @Override
        protected void publishResults(CharSequence constraint, FilterResults results) {
            List<Pokemon> filtered = (List<Pokemon>) results.values;
            notifyDataSetChanged();
        }
    }
}

And here is how it is implemented in MainActivity.java:

package edu.harvard.cs50.pokedex;

import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;

import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.SearchView;

public class MainActivity extends AppCompatActivity implements SearchView.OnQueryTextListener {
    private RecyclerView recyclerView;
    private PokedexAdapter adapter;  //private RecyclerView.Adapter adapter;
    private RecyclerView.LayoutManager layoutManager;

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

        recyclerView = findViewById(R.id.recycler_view);
        adapter = new PokedexAdapter(getApplicationContext());
        layoutManager = new LinearLayoutManager(this);

        recyclerView.setAdapter(adapter);
        recyclerView.setLayoutManager(layoutManager);
    }
    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.main_menu, menu);
        MenuItem searchItem = menu.findItem(R.id.action_search);
        SearchView searchView = (SearchView) searchItem.getActionView();
        searchView.setOnQueryTextListener(this);

        return true;
    }

    @Override
    public boolean onQueryTextChange(String newText) {
        adapter.getFilter().filter(newText);
        return false;
    }

    @Override
    public boolean onQueryTextSubmit(String newText) {
        adapter.getFilter().filter(newText);
        return false;
    }
}

Body:
I had a similar issue which was caused by the following :

@Override
public int getItemCount() {
    return pokemon.size();
}

I believe it can happen that pokemon is not initiated and therefore doesn't have a return value (or equals "null")

I added an if statement that would just return 0 if pokemon is null

@Override
public int getItemCount() {
    if (pokemon != null) {
        return pokemon.size();
    } else {
        return 0;
    }
}

I also have changed the variable name pokemon to the variable name of my Array List that holds the filtered items.


问:
string manipulation: partly convert to lowercase
As the title says: What's best way of converting a string from any-case to lowercase keeping a portion unchanged? e.g. a string like: FormatDate(%M)==2 or stArTDate(%Y/%m)==11/3 and I want to convert it to formatdate(%M)==2 or startdate(%Y/%m)==11/3 i.e. change it to lowercase except the part in between the braces (). For the first example, I came up something like this:

```<code>>>> import re
>>> fdt = re.compile('(F|f)(O|o)(R|r)(M|m)(A|a)(T|t)(D|d)(A|a)(T|t)(E|e)\(')
>>> ss = "forMatDate(%M)==2"
>>> if fdt.match(ss):
...   SS = ss.split('(')
...   SS[0] = SS[0].lower()
...   ss = "(".join(SS)
...
>>> print ss
formatdate(%M)==2
</code>```

Whilst it works just fine, I didn't quite like it doing this way. The regular expression is ugly and it makes thing pretty much restricted to a particular string. Is there any better (hence, dynamic) way of doing that? Thanks in advance. Cheers!!

Update:

I probably didn't say it very clearly: it's not always formatdate(), sometimes it's startdate() or enddate() along with UserName==JohnDee and so on.. (it's part of the user-input) but the format is always the same and I wanted something reusable. So, this is the updated version based on Krumelur's script.

```<code>>>> fdt = re.compile('\(%[dmwyMW].*\)')
>>> ss = "formatDate(%M)==4"
>>> st = "UserName==JohnDee"
>>>
>>> def dt_lower(sX):
...   if fdt.search(sX):
...     p1,p2 = sX.split('(',1)
...     sX = "%s(%s" % (p1.lower(), p2)
...   else: sX = sX.lower()
...   return sX
...
>>> print dt_lower(ss)
formatdate(%M)==4
>>>
>>> print dt_lower(st)
username==johndee
</code>```

This is exactly what I wanted. Thanks everyone for helping. Cheers!!

答:
I don't think you can get much more "Pythonic" than this:

```<code>Python 2.7.1 (r271:86832, May 27 2011, 21:41:45)
[GCC 4.2.1 (Apple Inc. build 5664)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> ss = "forMatDate(%M)==2"
>>> if ss.lower().startswith('formatdate'):
...     i,j = ss.split('(', 1)
...     ss = '('.join((i.lower(), j))
...
>>> ss
'formatdate(%M)==2'
</code>```

No need for regular expressions, just built-in string methods.

Also works in Python 3.2.

ContentLicense: CC BY-SA 3.0

Body:
As the title says: What's best way of converting a string from any-case to lowercase keeping a portion unchanged? e.g. a string like: FormatDate(%M)==2 or stArTDate(%Y/%m)==11/3 and I want to convert it to formatdate(%M)==2 or startdate(%Y/%m)==11/3 i.e. change it to lowercase except the part in between the braces (). For the first example, I came up something like this:

>>> import re
>>> fdt = re.compile('(F|f)(O|o)(R|r)(M|m)(A|a)(T|t)(D|d)(A|a)(T|t)(E|e)\(')
>>> ss = "forMatDate(%M)==2"
>>> if fdt.match(ss):
...   SS = ss.split('(')
...   SS[0] = SS[0].lower()
...   ss = "(".join(SS)
...
>>> print ss
formatdate(%M)==2

Whilst it works just fine, I didn't quite like it doing this way. The regular expression is ugly and it makes thing pretty much restricted to a particular string. Is there any better (hence, dynamic) way of doing that? Thanks in advance. Cheers!!

Update:

I probably didn't say it very clearly: it's not always formatdate(), sometimes it's startdate() or enddate() along with UserName==JohnDee and so on.. (it's part of the user-input) but the format is always the same and I wanted something reusable. So, this is the updated version based on Krumelur's script.

>>> fdt = re.compile('\(%[dmwyMW].*\)')
>>> ss = "formatDate(%M)==4"
>>> st = "UserName==JohnDee"
>>>
>>> def dt_lower(sX):
...   if fdt.search(sX):
...     p1,p2 = sX.split('(',1)
...     sX = "%s(%s" % (p1.lower(), p2)
...   else: sX = sX.lower()
...   return sX
...
>>> print dt_lower(ss)
formatdate(%M)==4
>>>
>>> print dt_lower(st)
username==johndee

This is exactly what I wanted. Thanks everyone for helping. Cheers!!

Body:
I don't think you can get much more "Pythonic" than this:

Python 2.7.1 (r271:86832, May 27 2011, 21:41:45)
[GCC 4.2.1 (Apple Inc. build 5664)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> ss = "forMatDate(%M)==2"
>>> if ss.lower().startswith('formatdate'):
...     i,j = ss.split('(', 1)
...     ss = '('.join((i.lower(), j))
...
>>> ss
'formatdate(%M)==2'

No need for regular expressions, just built-in string methods.

Also works in Python 3.2.


问:
How to move blazor components to a different assembly
I have a blazor server project, and I wanted to move some of the shared components to a different assembly to see if it would make a difference in the compilation times (bonus for letting me know if this would work...), but this isn't going so well.

In VS2019 the razor.cs parts of the components are at the same level as the .razor parts (rather than being 'under' them as they are in the blazor project), and other components can't find them. Oddly the project builds and runs, but the components are just drawn blank. I've cleaned, rebuilt, deleted the bin and obj folders, restarted VS etc, and no changes.

I have updated the _Imports.razor file, and everything should be as it needs to be, but this just isn't working.

Any help appreciated!

EDIT: This is 'Under':

And this is how it's displaying:

答:
Oddly the project builds and runs, but the components are just drawn blank.

Only the .cs base part is gettting linked in, your .razor code is ignored. So all your components render as their base class, empty.

You need build-time support for compiling the .razor to intermediate C#.

You can move the pages to  a Razor Class Library, and then do not check the 'suport pages and views' box.

But that project type is more aimed at independent components, providing their own css files etc. That may or not suit your needs.

In general I wouldn't expect much difference in build times, they could even go up. So you may want to reconsider this.


问:
How to merge elements of a collection in one array using Eloquent
I'm trying the following:

I'm getting all clinic_tests related to my patients using the following function:

```<code>public function getPatientsClinicTests(Specialist $id)
  {
        $patientClinicTests = $id->patients()
            ->with('PatientClinicTests', 'PatientClinicTests.Patient.User')
            ->get()
            ->pluck('PatientClinicTests')
            ->filter(function ($value) { return !empty($value); });

        $result = [];
        foreach ($patientClinicTests as $array) {
            $result = array_merge($result, $array->toArray());
        }

        return $result;
    }
</code>```

First group of code:

```<code>$patientClinicTests = $id->patients()
                ->with('PatientClinicTests', 'PatientClinicTests.Patient.User')
                ->get()
                ->pluck('PatientClinicTests')
                ->filter(function ($value) { return !empty($value); });
</code>```

Brings me a collection of arrays as follows:

```<code>[
  [
    {
      "id": 16,
      "patient_id": 7,
      "medical_condition_id": null,
      "patient": {
        "id": 7,
        "user_id": 7,
        "pigment_id": 14,
        "id_medical_history": "6219116421",
        "user": {
          "id": 7,
          "name": "Austen Wiegand",
        }
      }
    },
    .....
  ],
  [
    {
      "id": 22,
      "patient_id": 1,
      "medical_condition_id": null,
      "patient": {
        "id": 7,
        "user_id": 1,
        "pigment_id": 14,
        "id_medical_history": "6219116421",
        "user": {
          "id": 7,
          "name": "Gregor Wiegand",
        }
      }
    },
    .......
  ]
]
</code>```

As I need to return one array of elements I combine the arrays I got as follows:

```<code>$result = [];
    foreach ($patientClinicTests as $array) {
        $result = array_merge($result, $array->toArray());
    }

    return $result;
</code>```

This returns one array as follows:

```<code>[
    {
      "id": 16,
      "patient_id": 7,
      "medical_condition_id": null,
      "patient": {
        "id": 7,
        "user_id": 7,
        "pigment_id": 14,
        "id_medical_history": "6219116421",
        "user": {
          "id": 7,
          "name": "Austen Wiegand",
        }
      }
    },
    {
      "id": 22,
      "patient_id": 1,
      "medical_condition_id": null,
      "patient": {
        "id": 7,
        "user_id": 1,
        "pigment_id": 14,
        "id_medical_history": "6219116421",
        "user": {
          "id": 7,
          "name": "Gregor Wiegand",
        }
      }
    },
    .......
]
</code>```

I would like to know if there is a smarter option to return as one array of elements using Eloquent instead a foreach statement.

Thanks a lot for your help!

答:
Flatten method helps me to give a single array without using foreach statement an array_merge() function:

```<code>$patientClinicTests = $id->patients()
            ->with('PatientClinicTests', 'PatientClinicTests.Patient.User')
            ->get()
            ->pluck('PatientClinicTests')
            ->filter(function ($value) { return !empty($value); })->flatten()->all();
</code>```

I will test using table joining as it has been recommended

Body:
I'm trying the following:

I'm getting all clinic_tests related to my patients using the following function:

public function getPatientsClinicTests(Specialist $id)
  {
        $patientClinicTests = $id->patients()
            ->with('PatientClinicTests', 'PatientClinicTests.Patient.User')
            ->get()
            ->pluck('PatientClinicTests')
            ->filter(function ($value) { return !empty($value); });

        $result = [];
        foreach ($patientClinicTests as $array) {
            $result = array_merge($result, $array->toArray());
        }

        return $result;
    }

First group of code:

$patientClinicTests = $id->patients()
                ->with('PatientClinicTests', 'PatientClinicTests.Patient.User')
                ->get()
                ->pluck('PatientClinicTests')
                ->filter(function ($value) { return !empty($value); });

Brings me a collection of arrays as follows:

[
  [
    {
      "id": 16,
      "patient_id": 7,
      "medical_condition_id": null,
      "patient": {
        "id": 7,
        "user_id": 7,
        "pigment_id": 14,
        "id_medical_history": "6219116421",
        "user": {
          "id": 7,
          "name": "Austen Wiegand",
        }
      }
    },
    .....
  ],
  [
    {
      "id": 22,
      "patient_id": 1,
      "medical_condition_id": null,
      "patient": {
        "id": 7,
        "user_id": 1,
        "pigment_id": 14,
        "id_medical_history": "6219116421",
        "user": {
          "id": 7,
          "name": "Gregor Wiegand",
        }
      }
    },
    .......
  ]
]

As I need to return one array of elements I combine the arrays I got as follows:

$result = [];
    foreach ($patientClinicTests as $array) {
        $result = array_merge($result, $array->toArray());
    }

    return $result;

This returns one array as follows:

[
    {
      "id": 16,
      "patient_id": 7,
      "medical_condition_id": null,
      "patient": {
        "id": 7,
        "user_id": 7,
        "pigment_id": 14,
        "id_medical_history": "6219116421",
        "user": {
          "id": 7,
          "name": "Austen Wiegand",
        }
      }
    },
    {
      "id": 22,
      "patient_id": 1,
      "medical_condition_id": null,
      "patient": {
        "id": 7,
        "user_id": 1,
        "pigment_id": 14,
        "id_medical_history": "6219116421",
        "user": {
          "id": 7,
          "name": "Gregor Wiegand",
        }
      }
    },
    .......
]

I would like to know if there is a smarter option to return as one array of elements using Eloquent instead a foreach statement.

Thanks a lot for your help!

Body:
Flatten method helps me to give a single array without using foreach statement an array_merge() function:

$patientClinicTests = $id->patients()
            ->with('PatientClinicTests', 'PatientClinicTests.Patient.User')
            ->get()
            ->pluck('PatientClinicTests')
            ->filter(function ($value) { return !empty($value); })->flatten()->all();

I will test using table joining as it has been recommended


问:
Add a class depending on leaflet js zoom level
Been having an issue with one of my maps that uses leaflet.js.

I have some elements that are present on the map at a zoom level of 6 and higher (as a reference, 1 is world view - so the higher the number the more granular the view).

I need to add a class when the map is at a zoom level greater than 6 to a class to ensure it doesn't appear on the map. I would need to ensure the function is continually loaded every time there is a change. I think this is an event listener?

Trouble is I am not terribly good with javascript and I am struggling to pull the information I need through. I have hit some roadblocks lately and my confidence is knocked.

I have some pseudo code I have written.

```<code>    function myFunction() {
if zoom > 4 {
    element.classList.add("disappear");
}
};

var element = document.getElementById("dma-marker-icon leaflet-marker-icon leaflet-zoom-animated leaflet-clickable");
myFunction() // Call listener function at run time
addListener(myFunction) // Attach listener function on state changes
</code>```

Could you please help me refine this? Thanks so much.

答:
There's an event on a leaflet map which fires after the map zoom has changed - zoomend. So if you listen for that event, you can add or remove the class on your target element accordingly. You don't show much of your code so the variable names here will probably not match yours, but ...

```<code>myMap.on('zoomend', myFunction);

function myFunction(e) {
   if myMap.getZoom() > 4 {
    element.classList.add("disappear");
 }
 else {
    element.classList.remove("disappear");
 }
}
</code>```

Body:
Been having an issue with one of my maps that uses leaflet.js.

I have some elements that are present on the map at a zoom level of 6 and higher (as a reference, 1 is world view - so the higher the number the more granular the view).

I need to add a class when the map is at a zoom level greater than 6 to a class to ensure it doesn't appear on the map. I would need to ensure the function is continually loaded every time there is a change. I think this is an event listener?

Trouble is I am not terribly good with javascript and I am struggling to pull the information I need through. I have hit some roadblocks lately and my confidence is knocked.

I have some pseudo code I have written.

    function myFunction() {
if zoom > 4 {
    element.classList.add("disappear");
}
};

var element = document.getElementById("dma-marker-icon leaflet-marker-icon leaflet-zoom-animated leaflet-clickable");
myFunction() // Call listener function at run time
addListener(myFunction) // Attach listener function on state changes

Could you please help me refine this? Thanks so much.

Body:
There's an event on a leaflet map which fires after the map zoom has changed - zoomend. So if you listen for that event, you can add or remove the class on your target element accordingly. You don't show much of your code so the variable names here will probably not match yours, but ...

myMap.on('zoomend', myFunction);

function myFunction(e) {
   if myMap.getZoom() > 4 {
    element.classList.add("disappear");
 }
 else {
    element.classList.remove("disappear");
 }
}


问:
Singleton pattern in flutter
I have the following singleton

```<code>class WebSocketSingleton {

   IOWebSocketChannel _channel;

   WebSocketSingleton._privateConstructor();

   static final WebSocketSingleton _instance = WebSocketSingleton._privateConstructor();

   static WebSocketSingleton get instance => _instance;

   IOWebSocketChannel get channel{
   if(_channel == null){
      debugPrint("Creating new channel");
      _channel =  IOWebSocketChannel.connect(
         "wss://42zn68xb57.execute-api.us-east-1.amazonaws.com/Test");
    }

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

Every time I call WebSocketSingleton.instance it created a new instance of IOWebSocketChannel.

Questions:

Shouldn't the WebSocketSingleton return a previously created instance of the IOWebSocketChannel instead of creating a new one every time I call WebSocketSingleton.instance?

答:
I think there is some issue in your IOWebSocketChannel.connect which is not able to create an instance.

Here is the similar code like yours except I am using default constructor when creating a new instance and "creating new channel" is printed only once.

```<code>class Channel {}

class Singleton {
  Singleton._();

  static final Singleton _instance = Singleton._();

  static Singleton get instance => _instance;

  Channel _channel;

  Channel get channel {
    if (_channel == null) {
      print("Creating new channel");
      _channel = Channel();
    }

    return _channel;
  }
}

void main() {
  Singleton.instance.channel;
  Singleton.instance.channel;
}
</code>```

Title: Singleton pattern in flutter

Body:
I have the following singleton

class WebSocketSingleton {

   IOWebSocketChannel _channel;

   WebSocketSingleton._privateConstructor();

   static final WebSocketSingleton _instance = WebSocketSingleton._privateConstructor();

   static WebSocketSingleton get instance => _instance;

   IOWebSocketChannel get channel{
   if(_channel == null){
      debugPrint("Creating new channel");
      _channel =  IOWebSocketChannel.connect(
         "wss://42zn68xb57.execute-api.us-east-1.amazonaws.com/Test");
    }

    return _channel;
   }
}

Every time I call WebSocketSingleton.instance it created a new instance of IOWebSocketChannel.

Questions:

Shouldn't the WebSocketSingleton return a previously created instance of the IOWebSocketChannel instead of creating a new one every time I call WebSocketSingleton.instance?

Body:
I think there is some issue in your IOWebSocketChannel.connect which is not able to create an instance.

Here is the similar code like yours except I am using default constructor when creating a new instance and "creating new channel" is printed only once.

class Channel {}

class Singleton {
  Singleton._();

  static final Singleton _instance = Singleton._();

  static Singleton get instance => _instance;

  Channel _channel;

  Channel get channel {
    if (_channel == null) {
      print("Creating new channel");
      _channel = Channel();
    }

    return _channel;
  }
}

void main() {
  Singleton.instance.channel;
  Singleton.instance.channel;
}


问:
Convert decimal to string
While converting decimal value 0.00005 to string the code converts it to 5E-05.
The value 0.00005 is from a DataTable row.
How do I restrict converting the same to keep it 0.00005 instead of 5E-05? </p>

答:
Use the decimal.ToString override to specify a formatting.

```<code> decimal val = 0.00005 ;
 string str = amount.ToString("0.00");
</code>```

Or, it cannot be done on one line.

```<code>decimal val = 0.00005 ;
string str = amount.ToString("0.00").Replace(".00", String.Empty);
</code>```

When using String.Format.

```<code>Console.WriteLine("{0:0.00}", amount);
</code>```

Title: Convert decimal to string

Body:
Use the decimal.ToString override to specify a formatting.

 decimal val = 0.00005 ;
 string str = amount.ToString("0.00");

Or, it cannot be done on one line.

decimal val = 0.00005 ;
string str = amount.ToString("0.00").Replace(".00", String.Empty);

When using String.Format.

Console.WriteLine("{0:0.00}", amount);


问:
Create Custom SQL Server Role in SQL 2008 Server
I want to add new custom SQL Server Role and assign the new users to these appropriate roles respectively.  I try to find how to create role, but I could not find the place to add that.  Could you please guide me how to achieve my requirement?</p>

答:
Well I don't have SQL server installed right now so I can't check. But my knowledge of SQL tells me :

creating a role :

```<code>create role <rolename>;
</code>```

granting privilages :

```<code>grant <privilages> on <relation> to <rolename>;
</code>```

revoking privilages :

```<code>revoke <priv> on <rel> from <rolename>;
</code>```

grant role to user :

```<code>grant <rolename> to user;
</code>```

You can also create the hierarchy of it :
e.g.>

```<code>create role supervisor;
grant select, insert on db.table to supervisor;
create role manager;
grant supervisor to manager;

grant manager to John;
</code>```

This is the standard SQL way. It is not available yet in current versions of some DBMS. Not sure about SQL server.

Body:
Well I don't have SQL server installed right now so I can't check. But my knowledge of SQL tells me :

creating a role :

create role <rolename>;

granting privilages :

grant <privilages> on <relation> to <rolename>;

revoking privilages :

revoke <priv> on <rel> from <rolename>;

grant role to user :

grant <rolename> to user;

You can also create the hierarchy of it :
e.g.>

create role supervisor;
grant select, insert on db.table to supervisor;
create role manager;
grant supervisor to manager;

grant manager to John;

This is the standard SQL way. It is not available yet in current versions of some DBMS. Not sure about SQL server.


问:
Wordpress Hacked Website JS:Fakepush-A [Trj]
today my client told me that his website automatically redirect to another one external scam website.
On first sight no problem in the file directories, and no injections in the fields of the settings.

Wordfence no report any type of warning, but the Avast Antivirus in the client machine report a trojan warning:

"JS:Fakepush-A [Trj]" infection

Wordpress version 5.4.1
Theme: Newspapaer V 6.6.4

Any ideas?

答:
There are multiple things you need to check.

The redirect that you speak of can be present in header.php, footer.php, any javascript file that loads. Check for malicious files in wp-content/upload folder.

You will need to check database tables as well.

I would recommend installing Wordfence and scanning the site as well.

Once you remove and test it you will need to improve the security of it - check all the plugins are up to date and if any of them have any vulnerabilities. I found this website very useful: https://wpvulndb.com/plugins


问:
RabbitMQ publisher confirms with topic exchange - BasicAcks only fires once the first time
Using a topic exchange, I would like to have a publish/subscribe messaging pattern with the following features:

Have "publisher confirms" implemented.

Have the consumer acknowledge each message as well once it has processed it.

Use routing keys to route messages to one or more consumers.

Have persistent consumer queues so if the consumer application is down temporarily, it can pick up messages from its queue when it comes back up.

So I have created 2 console applications (Send and Receive) to test the above.

Send

```<code>    static void Main(string[] args)
    {

        Console.WriteLine(" Type [exit] to exit.");

        Publisher publisher = new Publisher();

        do
        {
            var userInput = Console.ReadLine();
            if (userInput == "exit")
            {
                break;
            }

            publisher.SendMessageToBroker("localhost", "main", "user.update", userInput);

        } while (true);
    }
</code>```

Publisher

```<code>public class Publisher
{
    const string ExchangeType = "topic";

    Dictionary<ulong, string> unConfirmedMessageTags = new Dictionary<ulong, string>();

    public void SendMessageToBroker(string host, string exchangeName, string routingKey, string message)
    {

        var factory = new ConnectionFactory() { HostName = host };
        using (var connection = factory.CreateConnection())
        using (var channel = connection.CreateModel())
        {
            channel.BasicAcks += (sender, ea) => OnBasicAcks(ea.Multiple, ea.DeliveryTag);
            channel.BasicNacks += (sender, ea) => OnBasicNacks(ea.Multiple, ea.DeliveryTag);

            channel.ConfirmSelect();

            channel.ExchangeDeclare(exchangeName, ExchangeType);

            var body = Encoding.UTF8.GetBytes(message);

            var properties = channel.CreateBasicProperties();
            properties.Persistent = true;

            unConfirmedMessageTags.TryAdd(channel.NextPublishSeqNo, message);

            channel.BasicPublish(exchange: exchangeName,
                routingKey: routingKey,
                basicProperties: properties,
                body: body);

            Console.WriteLine(" [x] Sent {0}", message);
        }
    }

    private void OnBasicNacks(bool multiple, ulong deliveryTag)
    {
        if (multiple)
        {
            Console.WriteLine("Messages with delivery tag LESS THAN {0} have been LOST and must be resent.", deliveryTag);
        }
        else
        {
            Console.WriteLine("Message with delivery tag {0} has been LOST and must be resent.", deliveryTag);
        }
    }

    private void OnBasicAcks(bool multiple, ulong deliveryTag)
    {
        if (multiple)
        {
            var confirmed = unConfirmedMessageTags.Where(k => k.Key <= deliveryTag);
            foreach (var entry in confirmed)
            {
                unConfirmedMessageTags.Remove(entry.Key);
                Console.WriteLine("Message with delivery tag {0} has been confirmed and deleted.", entry.Key);
            }

        }
        else
        {
            unConfirmedMessageTags.Remove(deliveryTag);
            Console.WriteLine("Message with delivery tag {0} has been confirmed and deleted.", deliveryTag);
        }

    }
}
</code>```

}

Receive

```<code>    static void Main(string[] args)
    {
        const string ExchangeName = "main";
        const string QueueName = "q1";
        const string ExchangeType = "topic";
        const string RoutingKey = "user.update";

        var factory = new ConnectionFactory() { HostName = "localhost" };
        using(var connection = factory.CreateConnection())
        using(var channel = connection.CreateModel())
        {
            channel.ExchangeDeclare(ExchangeName, ExchangeType);

            channel.QueueDeclare(queue: QueueName,
                durable: true,
                autoDelete: false,
                exclusive: false,
                arguments: null);

            channel.QueueBind(QueueName, ExchangeName, RoutingKey);

            //channel.BasicQos(prefetchSize: 0, prefetchCount: 1, global: false);

            var consumer = new EventingBasicConsumer(channel);

            consumer.Received += (model, ea) => Basic_Ack(channel, ea.DeliveryTag, ea.Body);

            channel.BasicConsume(queue: QueueName, autoAck: false, consumer: consumer);

            Console.WriteLine(" Press [enter] to exit.");
            Console.ReadLine();
        }
    }

    private static void Basic_Ack(IModel channel, ulong deliveryTag, ReadOnlyMemory<byte> body)
    {
        var message = Encoding.UTF8.GetString(body.ToArray());
        Console.WriteLine(" [x] Received {0}", message);

        Thread.Sleep(2000);

        channel.BasicAck(deliveryTag: deliveryTag, multiple: false);

        Console.WriteLine(" [x] Processed {0}", message);
    }
}
</code>```

The problem is the OnBasicAcks in my Send program only gets called once for the first message.

答:
For anyone else out there who may hit this issue, I was opening a connection and channel (virtual connection) for every publish which is discouraged:

"Connections are meant to be long-lived. Opening a connection for every operation (e.g. publishing a message) would be very inefficient and is highly discouraged."

Also see here:

"Publisher confirms are enabled at the channel level with the ConfirmSelect method... This method must be called on every channel that you expect to use publisher confirms. Confirms should be enabled just once, not for every message published."

Switching to using a long-lived connection solved the issue for me.

Body:
Using a topic exchange, I would like to have a publish/subscribe messaging pattern with the following features:

Have "publisher confirms" implemented.

Have the consumer acknowledge each message as well once it has processed it.

Use routing keys to route messages to one or more consumers.

Have persistent consumer queues so if the consumer application is down temporarily, it can pick up messages from its queue when it comes back up.

So I have created 2 console applications (Send and Receive) to test the above.

Send

    static void Main(string[] args)
    {

        Console.WriteLine(" Type [exit] to exit.");

        Publisher publisher = new Publisher();

        do
        {
            var userInput = Console.ReadLine();
            if (userInput == "exit")
            {
                break;
            }

            publisher.SendMessageToBroker("localhost", "main", "user.update", userInput);

        } while (true);
    }

Publisher

public class Publisher
{
    const string ExchangeType = "topic";

    Dictionary<ulong, string> unConfirmedMessageTags = new Dictionary<ulong, string>();

    public void SendMessageToBroker(string host, string exchangeName, string routingKey, string message)
    {

        var factory = new ConnectionFactory() { HostName = host };
        using (var connection = factory.CreateConnection())
        using (var channel = connection.CreateModel())
        {
            channel.BasicAcks += (sender, ea) => OnBasicAcks(ea.Multiple, ea.DeliveryTag);
            channel.BasicNacks += (sender, ea) => OnBasicNacks(ea.Multiple, ea.DeliveryTag);

            channel.ConfirmSelect();

            channel.ExchangeDeclare(exchangeName, ExchangeType);

            var body = Encoding.UTF8.GetBytes(message);

            var properties = channel.CreateBasicProperties();
            properties.Persistent = true;

            unConfirmedMessageTags.TryAdd(channel.NextPublishSeqNo, message);

            channel.BasicPublish(exchange: exchangeName,
                routingKey: routingKey,
                basicProperties: properties,
                body: body);

            Console.WriteLine(" [x] Sent {0}", message);
        }
    }

    private void OnBasicNacks(bool multiple, ulong deliveryTag)
    {
        if (multiple)
        {
            Console.WriteLine("Messages with delivery tag LESS THAN {0} have been LOST and must be resent.", deliveryTag);
        }
        else
        {
            Console.WriteLine("Message with delivery tag {0} has been LOST and must be resent.", deliveryTag);
        }
    }

    private void OnBasicAcks(bool multiple, ulong deliveryTag)
    {
        if (multiple)
        {
            var confirmed = unConfirmedMessageTags.Where(k => k.Key <= deliveryTag);
            foreach (var entry in confirmed)
            {
                unConfirmedMessageTags.Remove(entry.Key);
                Console.WriteLine("Message with delivery tag {0} has been confirmed and deleted.", entry.Key);
            }

        }
        else
        {
            unConfirmedMessageTags.Remove(deliveryTag);
            Console.WriteLine("Message with delivery tag {0} has been confirmed and deleted.", deliveryTag);
        }

    }
}

}

Receive

    static void Main(string[] args)
    {
        const string ExchangeName = "main";
        const string QueueName = "q1";
        const string ExchangeType = "topic";
        const string RoutingKey = "user.update";

        var factory = new ConnectionFactory() { HostName = "localhost" };
        using(var connection = factory.CreateConnection())
        using(var channel = connection.CreateModel())
        {
            channel.ExchangeDeclare(ExchangeName, ExchangeType);

            channel.QueueDeclare(queue: QueueName,
                durable: true,
                autoDelete: false,
                exclusive: false,
                arguments: null);

            channel.QueueBind(QueueName, ExchangeName, RoutingKey);

            //channel.BasicQos(prefetchSize: 0, prefetchCount: 1, global: false);

            var consumer = new EventingBasicConsumer(channel);

            consumer.Received += (model, ea) => Basic_Ack(channel, ea.DeliveryTag, ea.Body);

            channel.BasicConsume(queue: QueueName, autoAck: false, consumer: consumer);

            Console.WriteLine(" Press [enter] to exit.");
            Console.ReadLine();
        }
    }

    private static void Basic_Ack(IModel channel, ulong deliveryTag, ReadOnlyMemory<byte> body)
    {
        var message = Encoding.UTF8.GetString(body.ToArray());
        Console.WriteLine(" [x] Received {0}", message);

        Thread.Sleep(2000);

        channel.BasicAck(deliveryTag: deliveryTag, multiple: false);

        Console.WriteLine(" [x] Processed {0}", message);
    }
}

The problem is the OnBasicAcks in my Send program only gets called once for the first message.


问:
Alexa Flash Briefing API with SSML
I have created a simple flash briefing skill that reads from a rss feed. However it is pronouncing the name of the company wrong. I have reviewed the SSML page on the amazon developer site, but i do not see a way to get to the js that runs the skill. Is there any way to edit the js behind the skill if I am using the default API? Is there another solution short of writing a standalone skill?</p>

答:
It's not possible to do that yet. SSML is allowed in the Feed content only.

However you can up-vote the idea, you are not the first one who faces this issue.

Title: Alexa Flash Briefing API with SSML


问:
Convert string representation of list of dictionaries to list of dictionaries
This is string representation

```<code>Data = "[{'Date': '16-Sep-2019', 'Open': 10994.85, 'High': 11052.7, 'Low': 10968.2, 'Close': 11003.5, 'Shares Traded': 434449776, 'Turnover (Rs. Cr)': 15786.17}, {'Date': '17-Sep-2019', 'Open': 11000.1, 'High': 11000.1, 'Low': 10796.5, 'Close': 10817.6, 'Shares Traded': 482013044, 'Turnover (Rs. Cr)': 17721.93}]"
</code>```

i want it to be list representation

```<code>Data = [{'Date': '16-Sep-2019', 'Open': 10994.85, 'High': 11052.7, 'Low': 10968.2, 'Close': 11003.5, 'Shares Traded': 434449776, 'Turnover (Rs. Cr)': 15786.17}, {'Date': '17-Sep-2019', 'Open': 11000.1, 'High': 11000.1, 'Low': 10796.5, 'Close': 10817.6, 'Shares Traded': 482013044, 'Turnover (Rs. Cr)': 17721.93}]
</code>```

i tried every thing including json.loads(data),
Even after json.loads() it shows type as string.Please check in online compiler also.
Thankyou

Body:
This is string representation

Data = "[{'Date': '16-Sep-2019', 'Open': 10994.85, 'High': 11052.7, 'Low': 10968.2, 'Close': 11003.5, 'Shares Traded': 434449776, 'Turnover (Rs. Cr)': 15786.17}, {'Date': '17-Sep-2019', 'Open': 11000.1, 'High': 11000.1, 'Low': 10796.5, 'Close': 10817.6, 'Shares Traded': 482013044, 'Turnover (Rs. Cr)': 17721.93}]"

i want it to be list representation

Data = [{'Date': '16-Sep-2019', 'Open': 10994.85, 'High': 11052.7, 'Low': 10968.2, 'Close': 11003.5, 'Shares Traded': 434449776, 'Turnover (Rs. Cr)': 15786.17}, {'Date': '17-Sep-2019', 'Open': 11000.1, 'High': 11000.1, 'Low': 10796.5, 'Close': 10817.6, 'Shares Traded': 482013044, 'Turnover (Rs. Cr)': 17721.93}]

i tried every thing including json.loads(data),
Even after json.loads() it shows type as string.Please check in online compiler also.
Thankyou

Body:
Simply use eval function.

data=eval("[{'Date': '16-Sep-2019', 'Open': 10994.85, 'High': 11052.7, 'Low': 10968.2, 'Close': 11003.5, 'Shares Traded': 434449776, 'Turnover (Rs. Cr)': 15786.17}, {'Date': '17-Sep-2019', 'Open': 11000.1, 'High': 11000.1, 'Low': 10796.5, 'Close': 10817.6, 'Shares Traded': 482013044, 'Turnover (Rs. Cr)': 17721.93}]")
print(type(data))
print(data[0])

Output:

<class 'list'>
{'Date': '16-Sep-2019', 'Open': 10994.85, 'High': 11052.7, 'Low': 10968.2, 'Close': 11003.5, 'Shares Traded': 434449776, 'Turnover (Rs. Cr)': 15786.17}


问:
How can I untar multiple tar files over ssh?
I am attempting to untar multiple tar files over ssh:

```<code>ssh user@hostname "cat /dir/file*.tgz" | tar xvzf -
</code>```

The above only works on the first file match on the remote server. The local (dest) server only receives one file. The wildcard has been verified to match multiple files though.

Is there another way to do this?

答:
CarpeNoctem inspired me to go even further and provide a one-stop solution that require only a single ssh connection and does all the stuff streaming.

A tested proof concept (oneline formatted for readability):

```<code> (echo '#!/bin/sh';
  for a in /dir/file*.tgz
  do
      echo 'base64 -d <<"TARIMAGE" | tar xvzf -'
      base64 "$a"
      echo "TARIMAGE"
  done) | ssh -C remote 'cd /targetdir && sh -'
</code>```

Of course you'd actually want to reverse the roles of local and remote, in which case I'd recommend getting the script generation into a shell script instead:

gen_script.sh, chmod +x

```<code>#!/bin/bash
echo '#!/bin/sh';
for a in /dir/file*.tgz
do
    echo 'base64 -d <<"TARIMAGE" | tar xvzf -'
    base64 "$a"
    echo "TARIMAGE"
done
</code>```

invocation

```<code>scp gen_script.sh user@hostname:
ssh -C user@hostname /home/user/gen_script.sh | (cd targetdir && sh -)
</code>```

Loose ends, thoughts:

you can use uuencode, od, xxd, pgp or whatnot instead of base64

you can enable compression on ssh (ssh -C) to further optimize bandwidth

I made the targetdir/ step up myself to prevent accidents; you can let it off if you don't need it :)

Body:
I am attempting to untar multiple tar files over ssh:

ssh user@hostname "cat /dir/file*.tgz" | tar xvzf -

The above only works on the first file match on the remote server. The local (dest) server only receives one file. The wildcard has been verified to match multiple files though.

Is there another way to do this?

Body:
CarpeNoctem inspired me to go even further and provide a one-stop solution that require only a single ssh connection and does all the stuff streaming.

A tested proof concept (oneline formatted for readability):

 (echo '#!/bin/sh';
  for a in /dir/file*.tgz
  do
      echo 'base64 -d <<"TARIMAGE" | tar xvzf -'
      base64 "$a"
      echo "TARIMAGE"
  done) | ssh -C remote 'cd /targetdir && sh -'

Of course you'd actually want to reverse the roles of local and remote, in which case I'd recommend getting the script generation into a shell script instead:

gen_script.sh, chmod +x

#!/bin/bash
echo '#!/bin/sh';
for a in /dir/file*.tgz
do
    echo 'base64 -d <<"TARIMAGE" | tar xvzf -'
    base64 "$a"
    echo "TARIMAGE"
done

invocation

scp gen_script.sh user@hostname:
ssh -C user@hostname /home/user/gen_script.sh | (cd targetdir && sh -)

Loose ends, thoughts:

you can use uuencode, od, xxd, pgp or whatnot instead of base64

you can enable compression on ssh (ssh -C) to further optimize bandwidth

I made the targetdir/ step up myself to prevent accidents; you can let it off if you don't need it :)


问:
Comparing elements from a string to rows in a dataframe
I have rows in a dataframe that I would like to select if they contains numbers/numerical values which are included in the following string.

```<code>text_1="source="The previous low was 27,523. The 1.35 trillion ($22.5 million ) program could start in October. The number of people who left the country plunged 99.8 percent from a year earlier to 2,750, according to the data from the agency."
</code>```

Dataframe

```<code>Account       Sentences
51343     The subsidies are expected to form part of a second budget.
6376     The subsidies, totalling 2.35tn, are expected to form part of a second budget. New plans to allocate $22.5 billion to a new reimbursement programme.

31     The subsidies, totalling 1.35tn, are expected to form part of a second budget. New plans to allocate $22.5 billion to a new reimbursement programme.

2624     The way to a sports fan’s heart? Behind-the-scenes content from their favourite teams.
613    The subsidies, totalling 1.43 tn, are expected to form part of a second budget. New plans to allocate $21.5 billion to a new reimbursement programme.

764    The subsidies, totalling 1.35tn, are expected to form part of a second budget. New plans to allocate $22.5 billion to a new reimbursement programme.
</code>```

Desired output would be to create three columns:

one including all numbers that match with a row

one including all numbers that differ with those from text

one for boolean values (1 for matching all values; 0 if they do not match at all; 0.5 if there is at least one value in common).

The first thing that I was trying to do was to change all commas in full stops to avoid confusion in numbers in both text and Sentences column's rows.
Then, extracting all numbers from text in order to compare with each numerical value in rows.

```<code>numb=(re.findall("\d+[,.\d]\d+", text))
for i in df['Sentences']:
        print(re.findall("\d+[,.\d]\d+", i))
</code>```

Numbers to compare for each row in Sentences are: 27.523, 1.35, 22.5, 2.750, 99.8 (please notice that the comma should be converted in full stop).

Now, I should create the new columns with the findings to have

```<code>Account       Common                       Difference                    Match?
51343                            { 27.523, 1.35, 22.5, 2.750, 99.8 }       0
6376           22.5                          2.35                         0.5

31        {1.35, 22.5}              { 27.523, 2.750, 99.8 }               0.5

2624                             { 27.523, 1.35, 22.5, 2.750, 99.8 }       0
613                    { 27.523, 1.35, 22.5, 2.750, 99.8 }, {1.43, 21.5}   0

764       {1.35, 22.5}           { 27.523, 2.750, 99.8 }                  0.5
</code>```

Do you think it could be something doable? could you give me any advice to get these results?

答:
You can do something like that:

```<code># define variables
regex = r"(\d+[\.|,]?\d*)"
numbers = { "27.523", "1.35", "22.5", "2.750", "99.8" }

# define needed functions
def normalize(numbers):
    # converts , in numbers to .
    normalized = set()
    for number in numbers:
        normalized.add(re.sub(',', '.', number))
    return normalized

def get_difference(text):
    found_numbers = set(re.findall(regex, text))
    found_numbers = normalize(found_numbers)
    return found_numbers.difference(numbers)

def get_common(text):
    found_numbers = set(re.findall(regex, text))
    found_numbers = normalize(found_numbers)
    return found_numbers.intersection(numbers)

def get_match_ratio(text):
    found_numbers = set(re.findall(regex, text))
    found_numbers = normalize(found_numbers)
    common = found_numbers.intersection(numbers)
    if len(common) == len(numbers):
        return 1
    elif len(common) > 0:
        return 0.5
    else:
        return 0

# apply the functions and generate new columns
df["Common"] = df["Sentences"].apply(get_common)
df["Difference"] = df["Sentences"].apply(get_difference)
df["Match?"] = df["Sentences"].apply(get_match_ratio)
df.drop(columns=["Sentences"], inplace=True)
print(df.to_string())
#   Account        Common    Difference  Match?
#0    51343            {}            {}     0.0
#1     6376        {22.5}        {2.35}     0.5
#2       31  {1.35, 22.5}            {}     0.5
#3     2624            {}            {}     0.0
#4      613            {}  {21.5, 1.43}     0.0
#5      764  {1.35, 22.5}            {}     0.5
</code>```

According to the Difference column. I don't know how you got these values. So, I improvised trying to guess what could work for you.

Body:
I have rows in a dataframe that I would like to select if they contains numbers/numerical values which are included in the following string.

text_1="source="The previous low was 27,523. The 1.35 trillion ($22.5 million ) program could start in October. The number of people who left the country plunged 99.8 percent from a year earlier to 2,750, according to the data from the agency."

Dataframe

Account       Sentences
51343     The subsidies are expected to form part of a second budget.
6376     The subsidies, totalling 2.35tn, are expected to form part of a second budget. New plans to allocate $22.5 billion to a new reimbursement programme.

31     The subsidies, totalling 1.35tn, are expected to form part of a second budget. New plans to allocate $22.5 billion to a new reimbursement programme.

2624     The way to a sports fan’s heart? Behind-the-scenes content from their favourite teams.
613    The subsidies, totalling 1.43 tn, are expected to form part of a second budget. New plans to allocate $21.5 billion to a new reimbursement programme.

764    The subsidies, totalling 1.35tn, are expected to form part of a second budget. New plans to allocate $22.5 billion to a new reimbursement programme.

Desired output would be to create three columns:

one including all numbers that match with a row

one including all numbers that differ with those from text

one for boolean values (1 for matching all values; 0 if they do not match at all; 0.5 if there is at least one value in common).

The first thing that I was trying to do was to change all commas in full stops to avoid confusion in numbers in both text and Sentences column's rows.
Then, extracting all numbers from text in order to compare with each numerical value in rows.

numb=(re.findall("\d+[,.\d]\d+", text))
for i in df['Sentences']:
        print(re.findall("\d+[,.\d]\d+", i))

Numbers to compare for each row in Sentences are: 27.523, 1.35, 22.5, 2.750, 99.8 (please notice that the comma should be converted in full stop).

Now, I should create the new columns with the findings to have

Account       Common                       Difference                    Match?
51343                            { 27.523, 1.35, 22.5, 2.750, 99.8 }       0
6376           22.5                          2.35                         0.5

31        {1.35, 22.5}              { 27.523, 2.750, 99.8 }               0.5

2624                             { 27.523, 1.35, 22.5, 2.750, 99.8 }       0
613                    { 27.523, 1.35, 22.5, 2.750, 99.8 }, {1.43, 21.5}   0

764       {1.35, 22.5}           { 27.523, 2.750, 99.8 }                  0.5

Do you think it could be something doable? could you give me any advice to get these results?

Body:
You can do something like that:

# define variables
regex = r"(\d+[\.|,]?\d*)"
numbers = { "27.523", "1.35", "22.5", "2.750", "99.8" }

# define needed functions
def normalize(numbers):
    # converts , in numbers to .
    normalized = set()
    for number in numbers:
        normalized.add(re.sub(',', '.', number))
    return normalized

def get_difference(text):
    found_numbers = set(re.findall(regex, text))
    found_numbers = normalize(found_numbers)
    return found_numbers.difference(numbers)

def get_common(text):
    found_numbers = set(re.findall(regex, text))
    found_numbers = normalize(found_numbers)
    return found_numbers.intersection(numbers)

def get_match_ratio(text):
    found_numbers = set(re.findall(regex, text))
    found_numbers = normalize(found_numbers)
    common = found_numbers.intersection(numbers)
    if len(common) == len(numbers):
        return 1
    elif len(common) > 0:
        return 0.5
    else:
        return 0

# apply the functions and generate new columns
df["Common"] = df["Sentences"].apply(get_common)
df["Difference"] = df["Sentences"].apply(get_difference)
df["Match?"] = df["Sentences"].apply(get_match_ratio)
df.drop(columns=["Sentences"], inplace=True)
print(df.to_string())
#   Account        Common    Difference  Match?
#0    51343            {}            {}     0.0
#1     6376        {22.5}        {2.35}     0.5
#2       31  {1.35, 22.5}            {}     0.5
#3     2624            {}            {}     0.0
#4      613            {}  {21.5, 1.43}     0.0
#5      764  {1.35, 22.5}            {}     0.5

According to the Difference column. I don't know how you got these values. So, I improvised trying to guess what could work for you.


问:
Create a random binary variable for a subset of observations assigning 1 to a specific proportion of rows
I have a dataframe...

```<code>df <- tibble(
  id = 1:10,
  family = c("a","a","b","b","c", "d", "e", "f", "g", "h")
  )
</code>```

Families will only contain 2 members at most (so they're either individuals or pairs).

For individuals (families with only one row, i.e. id = 5:10), I want to create a column called 'random' that randomly assigns 50% of the entries as 1 and the rest as 0. All other rows (those belonging to families with 2 members) should also equal 0.

By the end, the data should look like the following (depending on which 50% of rows are assigned 1)...

```<code>df <- tibble(
  id = 1:10,
  family = c("a","a","b","b","c", "d", "e", "f", "g", "h"),
  random = c(0, 0, 0, 0, 1, 0, 1, 1, 0, 0)
  )
</code>```

I am mostly using Tidyverse and would like to include it within a pipe.

I am currently trying something along the lines of...

```<code>df %>%
   group_by(family) %>%
   mutate(random = if(n() == 1) *not sure what goes here* else 0)
</code>```

答:
We can assign 0 if number of rows in a family is greater than 1 else select a random value between 0 and 1.

```<code>library(dplyr)

df %>%
  group_by(family) %>%
  mutate(random = if(n() > 1) 0 else sample(0:1, 1))

#      id family random
#   <int> <chr>   <dbl>
# 1     1 a           0
# 2     2 a           0
# 3     3 b           0
# 4     4 b           0
# 5     5 c           1
# 6     6 d           1
# 7     7 e           0
# 8     8 f           0
# 9     9 g           0
#10    10 h           0
</code>```

If we want a fixed number of 1's and 0's for groups with 1 value we can use

```<code>df %>%
  add_count(family) %>%
   mutate(n = replace(n, n > 1, 0),
          n = replace(n, {inds = which(n == 1);sample(inds, length(inds)/2)}, 0))

# A tibble: 10 x 3
#      id family     n
#   <int> <chr>  <dbl>
# 1     1 a          0
# 2     2 a          0
# 3     3 b          0
# 4     4 b          0
# 5     5 c          1
# 6     6 d          0
# 7     7 e          0
# 8     8 f          1
# 9     9 g          1
#10    10 h          0
</code>```

Body:
I have a dataframe...

df <- tibble(
  id = 1:10,
  family = c("a","a","b","b","c", "d", "e", "f", "g", "h")
  )

Families will only contain 2 members at most (so they're either individuals or pairs).

For individuals (families with only one row, i.e. id = 5:10), I want to create a column called 'random' that randomly assigns 50% of the entries as 1 and the rest as 0. All other rows (those belonging to families with 2 members) should also equal 0.

By the end, the data should look like the following (depending on which 50% of rows are assigned 1)...

df <- tibble(
  id = 1:10,
  family = c("a","a","b","b","c", "d", "e", "f", "g", "h"),
  random = c(0, 0, 0, 0, 1, 0, 1, 1, 0, 0)
  )

I am mostly using Tidyverse and would like to include it within a pipe.

I am currently trying something along the lines of...

df %>%
   group_by(family) %>%
   mutate(random = if(n() == 1) *not sure what goes here* else 0)

Body:
We can assign 0 if number of rows in a family is greater than 1 else select a random value between 0 and 1.

library(dplyr)

df %>%
  group_by(family) %>%
  mutate(random = if(n() > 1) 0 else sample(0:1, 1))

#      id family random
#   <int> <chr>   <dbl>
# 1     1 a           0
# 2     2 a           0
# 3     3 b           0
# 4     4 b           0
# 5     5 c           1
# 6     6 d           1
# 7     7 e           0
# 8     8 f           0
# 9     9 g           0
#10    10 h           0

If we want a fixed number of 1's and 0's for groups with 1 value we can use

df %>%
  add_count(family) %>%
   mutate(n = replace(n, n > 1, 0),
          n = replace(n, {inds = which(n == 1);sample(inds, length(inds)/2)}, 0))

# A tibble: 10 x 3
#      id family     n
#   <int> <chr>  <dbl>
# 1     1 a          0
# 2     2 a          0
# 3     3 b          0
# 4     4 b          0
# 5     5 c          1
# 6     6 d          0
# 7     7 e          0
# 8     8 f          1
# 9     9 g          1
#10    10 h          0


问:
Why is my React delete function "deleting" the wrong object?

import React, { Component } from "react";
import User from "./components/User.js"
import Project from "./components/Project.js"
import CreateForm from "./CreateForm.js";
import DeleteForm from "./DeleteForm.js";

class App extends Component {
    constructor(props) {
        super(props);
        this.state = {
            projectList: [],
            myProjects: [],
            userList: [],
            currentUser: "Guest"
        };

        this.createProject = this.createProject.bind(this);
        this.deleteProject = this.deleteProject.bind(this);
        }

    createProject(title, desc, langs, len, exp) {
        this.setState({
            projectList: [...this.state.projectList, {
                title : title,
                description : desc,
                language : langs,
                length : len,
                experience : exp,
                user : this.state.currentUser
            }]
        });
    }

    deleteProject(title) {
        const projects = this.state.projectList.filter(
            p => p.title !== title
        );
        this.setState({projectList : projects});
    }

    render() {
        return(

                <CreateForm createProject = {this.createProject} />
                <DeleteForm deleteProject = {this.deleteProject} />

 Project List:

                {this.state.projectList.map((params) =>
                <Project {...params}/>)}

        );
    }

}

export default App;```
</div>
</div>
</p>

<p><div class="snippet" data-lang="js" data-hide="false" data-console="true" data-babel="false">
<div class="snippet-code">
<pre class="snippet-code-js lang-js prettyprint-override"><code>import React from "react";

class DeleteForm extends React.Component {
    constructor(props) {
      super(props);
      this.state = {
        title: ""
      };

      this.handleSubmit = this.handleSubmit.bind(this);
      this.handleInputChange = this.handleInputChange.bind(this);
    }

    handleSubmit(event) {

      event.preventDefault();

      this.props.deleteProject(
        this.state.title
      )

    }

    handleInputChange(event) {
      const target = event.target;
      const value = target.value;
      const name = target.name;

      this.setState({
        [name]: value
      });
    }

    render() {
      return (
        <div>
            <h2> Delete Project: </h2>
            <form onSubmit={this.handleSubmit}>
            <label>
                Title:
                <input
                name="title"
                type="textbox"
                checked={this.state.title}
                onChange={this.handleInputChange} />
            </label>
            <br />
            <input type="submit" value="Delete" />
            </form>
        </div>
      );
    }
  }

export default DeleteForm;</code>```

I have a bit of code here which attempts to "delete" created projects from my project list. It works by filtering any projects with a certain title out, and using that as the new project list. However, when I create more than one project, trying to delete the first project unrenders the second project, and then when I delete the second project after the first deletion, it unrenders the first project. Example: I create Car then Apple in that order, I delete Car, which deletes Apple, then I delete Apple, which deletes Car.

PS: I excluded some code to make things simpler.

答:
This issue happens because you haven't provided key prop to the JSX returned from the map function and hence when you delete an item, react isn't able to properly determine which element to remove from your DOM

Adding a unique key prop will work for you

```<code> {this.state.projectList.map((params) =>
            <Project key={params.title} {...params}/>
  )}
</code>```

Body:
import React, { Component } from "react";
import User from "./components/User.js"
import Project from "./components/Project.js"
import CreateForm from "./CreateForm.js";
import DeleteForm from "./DeleteForm.js";

class App extends Component {
    constructor(props) {
        super(props);
        this.state = {
            projectList: [],
            myProjects: [],
            userList: [],
            currentUser: "Guest"
        };

        this.createProject = this.createProject.bind(this);
        this.deleteProject = this.deleteProject.bind(this);
        }

    createProject(title, desc, langs, len, exp) {
        this.setState({
            projectList: [...this.state.projectList, {
                title : title,
                description : desc,
                language : langs,
                length : len,
                experience : exp,
                user : this.state.currentUser
            }]
        });
    }

    deleteProject(title) {
        const projects = this.state.projectList.filter(
            p => p.title !== title
        );
        this.setState({projectList : projects});
    }

    render() {
        return(

                <CreateForm createProject = {this.createProject} />
                <DeleteForm deleteProject = {this.deleteProject} />

 Project List:

                {this.state.projectList.map((params) =>
                <Project {...params}/>)}

        );
    }

}

export default App;

import React from "react";

class DeleteForm extends React.Component {
    constructor(props) {
      super(props);
      this.state = {
        title: ""
      };

      this.handleSubmit = this.handleSubmit.bind(this);
      this.handleInputChange = this.handleInputChange.bind(this);
    }

    handleSubmit(event) {

      event.preventDefault();

      this.props.deleteProject(
        this.state.title
      )

    }

    handleInputChange(event) {
      const target = event.target;
      const value = target.value;
      const name = target.name;

      this.setState({
        [name]: value
      });
    }

    render() {
      return (

 Delete Project:

            <form onSubmit={this.handleSubmit}>

                Title:
                <input
                name="title"
                type="textbox"
                checked={this.state.title}
                onChange={this.handleInputChange} />

            <input type="submit" value="Delete" />
            </form>

      );
    }
  }

export default DeleteForm;

I have a bit of code here which attempts to "delete" created projects from my project list. It works by filtering any projects with a certain title out, and using that as the new project list. However, when I create more than one project, trying to delete the first project unrenders the second project, and then when I delete the second project after the first deletion, it unrenders the first project. Example: I create Car then Apple in that order, I delete Car, which deletes Apple, then I delete Apple, which deletes Car.

PS: I excluded some code to make things simpler.

Body:
This issue happens because you haven't provided key prop to the JSX returned from the map function and hence when you delete an item, react isn't able to properly determine which element to remove from your DOM

Adding a unique key prop will work for you

 {this.state.projectList.map((params) =>
            <Project key={params.title} {...params}/>
  )}


问:
What data do I need to implement k nearest neighbor?
I currently have a reddit-clone type website. I'm trying to recommend posts based on the posts that my users have previously liked.

It seems like K nearest neighbor or k means are the best way to do this.

I can't seem to understand how to actually implement this. I've seen some mathematical formulas (such as the one on the k means wikipedia page), but they don't really make sense to me.

Could someone maybe recommend some pseudo code, or places to look so I can get a better feel on how to do this?

答: What you described sounds like a recommender system engine, not a clustering algorithm like k-means which in essence is an unsupervised approach. I cannot make myself a clear idea of what reddit uses actually, but I found some interesting post by googling around "recommender + reddit", e.g. Reddit, Stumbleupon, Del.icio.us and Hacker News Algorithms Exposed! Anyway, the k-NN algorithm (described in the top ten data mining algorithm, with pseudo-code on Wikipedia) might be used, or other techniques like Collaborative filtering (used by Amazon, for example), described in this good tutorial.</p>


问:
POST http://localhost:3000/login/aa/aa 404 (Not Found)
I have an angular app and a nodejs backend server. I want to get data from my backend but when I try to connect to it with Angular HTTPClient, it says: POST http://localhost:3000/login/aa/aa 404 (Not Found).However, when I put the link manually into the browser, it works perfectly fine. Here is some code:

service.ts

```<code>addUser(user: IUser): Observable<IUser> {
        return this.httpClient.post<IUser>(`http://localhost:3000/login/${user.email}/${user.passwort}`, user, {
            headers: new HttpHeaders({
                'Content-Type': 'application/json'
            })
        })
            .pipe(catchError(this.handleError));
    }
</code>```

index.js

```<code>var mysql = require('mysql');
var express = require('express');
var app = express();

const port = process.env.PORT || 3000;
[...]
app.get('/login/:email/:pw',function(req,res) {
  res.setHeader('Content-Type', 'application/json');
  var passwort = new Passwort(''+req.params.pw);
  passwort.comparePasswort();
  con.query("SELECT u.Email, u.Hash FROM User u WHERE u.Email LIKE "+ "'" + req.params.email+ "'", function(err, result ){
    if(err) throw err;
    console.log(result)
    res.send("test")
  })

});
</code>```

Thanks for every answer and for your time!

答:
Your route in your backend is set as a get request and not a post request.

You should either convert your request to a get in your service with this.httpClient.get... or convert to a post request in your backend with app.post.

The reason it works in your browser is that the browser performs a GET request when acessing something using the address bar.

Body:
I have an angular app and a nodejs backend server. I want to get data from my backend but when I try to connect to it with Angular HTTPClient, it says: POST http://localhost:3000/login/aa/aa 404 (Not Found).However, when I put the link manually into the browser, it works perfectly fine. Here is some code:

service.ts

addUser(user: IUser): Observable<IUser> {
        return this.httpClient.post<IUser>(`http://localhost:3000/login/${user.email}/${user.passwort}`, user, {
            headers: new HttpHeaders({
                'Content-Type': 'application/json'
            })
        })
            .pipe(catchError(this.handleError));
    }

index.js

var mysql = require('mysql');
var express = require('express');
var app = express();

const port = process.env.PORT || 3000;
[...]
app.get('/login/:email/:pw',function(req,res) {
  res.setHeader('Content-Type', 'application/json');
  var passwort = new Passwort(''+req.params.pw);
  passwort.comparePasswort();
  con.query("SELECT u.Email, u.Hash FROM User u WHERE u.Email LIKE "+ "'" + req.params.email+ "'", function(err, result ){
    if(err) throw err;
    console.log(result)
    res.send("test")
  })

});

Thanks for every answer and for your time!


问:
GROUP BY SUM CASE expression
I want to group by account number, but I am running into problems if I get multiple RATE_CD's for an account - I get a NONCOMPLIANT_CNT of 2, but I want it to be only 1 per account even if there is more than 1 RATE_CD.

Below is the SQL I'm playing around with, any ideas on how I can return the NONCOMPLIANT_CNT per account, and not roll up the count if there is more than 1 RATE_CD?

```<code>SELECT ID
    ,ACCOUNT_NBR SUM(CASE
            WHEN GROUP_CD = 'RED'
                AND TYPE_CD IN ('CHK')
                THEN 1
            ELSE 0
            END) AS 'COMPLIANT_CNT'
    ,SUM(CASE
            WHEN GROUP_CD = 'RED'
                AND TYPE_CD IN (
                    'CN'
                    ,'RN'
                    )
                AND RATE_CD <> 'BLK'
                THEN 1
            ELSE 0
            END) AS 'NONCOMPLIANT_CNT'
    ,SUM(CASE
            WHEN GROUP_CD = 'RED'
                AND TYPE_CD IN (
                    'CN'
                    ,'RN'
                    ,'CHK'
                    )
                THEN 1
            ELSE 0
            END) AS 'TOTAL_CNT'
FROM DETAIL
LEFT OUTER JOIN RATE_LOOKUP ACCOUNT_NBR = ACCOUNT_NBR
GROUP BY ID
    ,ACCOUNT_NBR
    ,RATE_CD
</code>```

答: If you only want 1 instead of how many actual, change your SUM() to MAX().  So if they have 5 entries, it would still show as at least 1, otherwise will be 0 for the given column aggregate.</p>

Title: GROUP BY SUM CASE expression

Body:
I want to group by account number, but I am running into problems if I get multiple RATE_CD's for an account - I get a NONCOMPLIANT_CNT of 2, but I want it to be only 1 per account even if there is more than 1 RATE_CD.

Below is the SQL I'm playing around with, any ideas on how I can return the NONCOMPLIANT_CNT per account, and not roll up the count if there is more than 1 RATE_CD?

SELECT ID
    ,ACCOUNT_NBR SUM(CASE
            WHEN GROUP_CD = 'RED'
                AND TYPE_CD IN ('CHK')
                THEN 1
            ELSE 0
            END) AS 'COMPLIANT_CNT'
    ,SUM(CASE
            WHEN GROUP_CD = 'RED'
                AND TYPE_CD IN (
                    'CN'
                    ,'RN'
                    )
                AND RATE_CD <> 'BLK'
                THEN 1
            ELSE 0
            END) AS 'NONCOMPLIANT_CNT'
    ,SUM(CASE
            WHEN GROUP_CD = 'RED'
                AND TYPE_CD IN (
                    'CN'
                    ,'RN'
                    ,'CHK'
                    )
                THEN 1
            ELSE 0
            END) AS 'TOTAL_CNT'
FROM DETAIL
LEFT OUTER JOIN RATE_LOOKUP ACCOUNT_NBR = ACCOUNT_NBR
GROUP BY ID
    ,ACCOUNT_NBR
    ,RATE_CD


问:
Redux: Execute reducers asynchronously?
I'm working on a bowling scoring system and I am quite confused as to why the following is not working as expected.

My state could look like this:

```<code>players: [
  {
    "id": "f44t0uagdyg",
    "name": "test-player",
    "currentFrame": 1,
    "active": false,
    "rolls": {
      "0": [2,3],
      "1": [1,5],
      "2": [],
      "3": [],
      "4": [],
      "5": [],
      "6": [],
      "7": [],
      "8": [],
      "9": [],
      "10": []
    },
    "totalWins": 0
  },
  {
    "id": "5gbxlu94zpr",
    "name": "test-player-2",
    "currentFrame": 1,
    "active": false,
    "rolls": {
      "1": [1,6],
      "2": [],
      "3": [],
      "4": [],
      "5": [],
      "6": [],
      "7": [],
      "8": [],
      "9": [],
      "10": []
    },
    "totalWins": 0
  }
]
</code>```

Now, whenever the user inputs a new roll, I want to add it to the store with these reducers (they work as intended):
To add the roll to the state I do the following:

```<code>    case ADD_ROLL:
      return {
      ...state,
      players: state.players.map((player) => {
        if (player.id === action.id) {
          return {
            ...player,
            rolls: {
              ...player.rolls,
              [action.frame]: [
                ...player.rolls[action.frame],
                action.roll
              ]
            }
          }
        }
        return player;
      })
    };
</code>```

To advance to the next frame (e.g. after the user input 2 rolls or rolled a strike) I do this:

```<code>       case NEXT_FRAME:
          return {
          ...state,
          players: state.players.map((player) => {
            if (player.id === action.id) {
              return {
                ...player,
                currentFrame: player.currentFrame + 1,
              }
            }
            return player;
          })
        }
</code>```

After the user clicks to confirm his input this advanceGame function is called to asses whether the game should advance to the next frame (if the user rolled twice already):

```<code>export const advanceGame = (players, roll) => {
  let currentPlayer = 0;
  const { currentFrame } = players[currentPlayer];

  if (players[currentPlayer].rolls[currentFrame].length === 2) {
    store.dispatch(nextFrame(players[currentPlayer].id));
    store.dispatch(addRoll(players[currentPlayer].currentFrame, roll, players[currentPlayer].id));
  } else {
    store.dispatch(addRoll(players[currentPlayer].currentFrame, roll, players[currentPlayer].id));
  }
};
</code>```

What I would like to happen is that that if the user rolled two times already , store.dispatch(nextFrame) updates the currentFrame to the next one and then adds the score to the appropriate frame. However, currently the frame only advance after 3 rolls have been made and 3 items are in the a roll Array.

How could I ensure that ADD_ROLL is only executed after NEXT_FRAME has 'finished'?

I have been staring at this for a really long time and I apologize if my question is to verbose. Happy to clear it up and appreciate any help!

答:
I don't know if it's exactly what your looking for but i think that reducer is ALWAYS synchrone.

Maybe you can try to make action async instead.
Redux-thunk was made for that https://github.com/reduxjs/redux-thunk

For example you can dispatch an action which do an api call, and the second action is only call if the api has returned his response.

You should find code that take time to execute and deplace it in the thunk, and only call the reducer to update your state.

Title: Redux: Execute reducers asynchronously?

Body:
I'm working on a bowling scoring system and I am quite confused as to why the following is not working as expected.

My state could look like this:

players: [
  {
    "id": "f44t0uagdyg",
    "name": "test-player",
    "currentFrame": 1,
    "active": false,
    "rolls": {
      "0": [2,3],
      "1": [1,5],
      "2": [],
      "3": [],
      "4": [],
      "5": [],
      "6": [],
      "7": [],
      "8": [],
      "9": [],
      "10": []
    },
    "totalWins": 0
  },
  {
    "id": "5gbxlu94zpr",
    "name": "test-player-2",
    "currentFrame": 1,
    "active": false,
    "rolls": {
      "1": [1,6],
      "2": [],
      "3": [],
      "4": [],
      "5": [],
      "6": [],
      "7": [],
      "8": [],
      "9": [],
      "10": []
    },
    "totalWins": 0
  }
]

Now, whenever the user inputs a new roll, I want to add it to the store with these reducers (they work as intended):
To add the roll to the state I do the following:

    case ADD_ROLL:
      return {
      ...state,
      players: state.players.map((player) => {
        if (player.id === action.id) {
          return {
            ...player,
            rolls: {
              ...player.rolls,
              [action.frame]: [
                ...player.rolls[action.frame],
                action.roll
              ]
            }
          }
        }
        return player;
      })
    };

To advance to the next frame (e.g. after the user input 2 rolls or rolled a strike) I do this:

       case NEXT_FRAME:
          return {
          ...state,
          players: state.players.map((player) => {
            if (player.id === action.id) {
              return {
                ...player,
                currentFrame: player.currentFrame + 1,
              }
            }
            return player;
          })
        }

After the user clicks to confirm his input this advanceGame function is called to asses whether the game should advance to the next frame (if the user rolled twice already):

export const advanceGame = (players, roll) => {
  let currentPlayer = 0;
  const { currentFrame } = players[currentPlayer];

  if (players[currentPlayer].rolls[currentFrame].length === 2) {
    store.dispatch(nextFrame(players[currentPlayer].id));
    store.dispatch(addRoll(players[currentPlayer].currentFrame, roll, players[currentPlayer].id));
  } else {
    store.dispatch(addRoll(players[currentPlayer].currentFrame, roll, players[currentPlayer].id));
  }
};

What I would like to happen is that that if the user rolled two times already , store.dispatch(nextFrame) updates the currentFrame to the next one and then adds the score to the appropriate frame. However, currently the frame only advance after 3 rolls have been made and 3 items are in the a roll Array.

How could I ensure that ADD_ROLL is only executed after NEXT_FRAME has 'finished'?

I have been staring at this for a really long time and I apologize if my question is to verbose. Happy to clear it up and appreciate any help!