JavaScript使用过滤器和循环从阵列中删除多个值

时间:2015-10-22 06:05:17

标签: javascript

我是新来的,在编写函数destroyer()以从数组中删除多个值时需要一些帮助。

destroyer()函数传入一个数组,并将其他数字作为参数传递。我们的想法是从数组中删除数字。

E.g。

destroyer([1, 2, 3, 1, 2, 3], 2, 3) 

输出:[1, 1]

destroyer(["tree", "hamburger", 53], "tree", 53) 

输出:["hamburger"]

destroyer([2, 3, 2, 3], 2, 3) 

输出:[]

注意:示例仅显示要删除的2个附加数字。但是函数destroyer()应该能够删除任意数量的值(即4个,5个或6个参数)。

但是,我的代码不会产生相同的结果。具体来说,使用console.log,我发现我的过滤器功能没有正确循环。

1)任何人都可以帮我调试吗?

2)有没有更好的方法来编写这个函数?

非常感谢!!!

function destroyer() {

  var args = Array.prototype.slice.call(arguments); 

  var itemToRemove = args.slice(1);
  console.log(itemToRemove);
  var newArr = args[0];
  console.log(newArr);

  function filterer(value) { 

    for (var i = 0; i < itemToRemove.length; i++) {
      console.log(i);
      console.log(itemToRemove[i]);
      if (value != itemToRemove[i]) {
        return value;
      }
    } 
   }

  return newArr.filter(filterer);
}

7 个答案:

答案 0 :(得分:4)

您的filterer功能可以更加简单:

function filterer (value) {
    return itemToRemove.indexOf(value) === -1;
}

答案 1 :(得分:0)

在时间复杂度方面,与对象属性查找相比,使用Array.prototype.indexOf()可能效率低下。我建议一次循环其他参数并构造一个目标元素作为键被销毁的对象。然后,您可以在传递给Array.prototype.filter()的过滤回调中检查给定值是否为目标。

function destroyer() {
    var arr = arguments.length && arguments[0] || [];
    var targets = {};
    for (var i = 1; i < arguments.length; i++) {
        targets[arguments[i]] = true;
    }
    return arr.filter(function (x) {
        return targets[x] === undefined;
    });
}

这种方法的一个缺点是,并非JS中的所有值都可以是对象的有效属性,因为属性必须是字符串。在这种情况下,您只是使用数字作为键,这些数字被隐式转换为字符串。

答案 2 :(得分:0)

我们可以在filter()方法中将参数传递给我们的回调函数。

function destroyer(arr) {
  return arr.filter(filterer(arguments)); // Pass arguments
}

function filterer(args) {
  return function(value) { // Actual filter function
    for (var i = 1; i < args.length; i++) {
      if (value === args[i]) // Seek
        return false; // Destroy
    }
    return true; // Otherwise keep
  };
}

这传递了 freeCodeCamp |的所有5个测试用例基本算法脚本|寻求和摧毁

答案 3 :(得分:-1)

以下代码将从数组中删除元素。它删除的元素由任何额外参数定义。 ...remove是一项ES6功能,可将额外参数聚合到单个数组中。

我将迭代...remove数组并从我们正在处理的主数组中删除该元素。

这是一个JSFiddle:https://jsfiddle.net/zzyopnnp/

大多数浏览器都不支持

...extra_parameters,您可能需要使用arguments对象。

function removeIndex(array, index) {if(index>-1){array.splice(index, 1);}}

function destroyer(array, ...remove) {
    remove.forEach(function(elem, index) {
        removeIndex(array, index);
    });
};

var arr = ["tree", "hamburger", 53];
destroyer(arr, "tree", 53);
console.log(arr);

答案 4 :(得分:-1)

一个简单的功能

public class SampleAdapter extends RecyclerView.Adapter<SampleAdapter.ViewHolder> {

// Declaring Variable to Understand which View is being worked on
// IF the view under inflation and population is header or Item
private static final int TYPE_HEADER = 0;
private static final int TYPE_ITEM = 1;
private static final int TYPE_FOOTER = 2;

private Activity mContext;
private ArrayList<DataModel> _mItems;
private int mLayout;
private String mProductHeadingTitle="Heading";
private String mProductHeadingSubTitle="SubHeading";
private String loadingText="LOADING";
private int visibility= View.VISIBLE;

public interface SampleAdapterInterface {
     void itemClicked(int position);
}

SampleAdapterInterface mCallBack;

public SampleAdapter(Activity context, ArrayList<DataModel> items, int item_layout) {
    if (_mItems != null) {
        _mItems.clear();
    }
    this.mContext = context;
    this._mItems = items;
    this.mLayout = item_layout;
    mCallBack = (SampleAdapterInterface) context;
}

@Override
public int getItemCount() {
    return _mItems.size()+2; // +2 for header and footer
}

@Override
public int getItemViewType(int position) {

    if (position==0)
        return TYPE_HEADER;
    else if(position==(_mItems.size()+1))
        return TYPE_FOOTER;

    return TYPE_ITEM;
}

public void setHeaderData(String title,String subTitle)
{
    this.mProductHeadingTitle=title;
    this.mProductHeadingSubTitle=subTitle;

    Log.d("LOG", "ProductHeadingTitle: " + mProductHeadingTitle);
    Log.d("LOG", "ProductHeadingSubTitle: " + mProductHeadingSubTitle);

    notifyDataSetChanged();
}

public void setFooterData(String loadingText,int visibility)
{
    this.loadingText=loadingText;
    this.visibility=visibility;

    Log.d("LOG", "LoadingText: " + loadingText);
    Log.d("LOG", "Visibility: " + visibility);

    notifyDataSetChanged();
}

@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {


    if (viewType == TYPE_HEADER)
    {
        View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.header_layout,parent,false);

        ViewHolder vhHeader = new ViewHolder(view,viewType);

        return vhHeader;
    }
    else if (viewType == TYPE_ITEM)
    {
        View view = LayoutInflater.from(parent.getContext()).inflate(mLayout,parent,false);

        //Creating ViewHolder and passing the object of type view
        ViewHolder vhItem = new ViewHolder(view,viewType);

        return vhItem;
    }
    else if (viewType == TYPE_FOOTER)
    {
        View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.footer_lyout,parent,false);

        ViewHolder vhFooter = new ViewHolder(view,viewType);

        return vhFooter;
    }
    return null;
}

@Override
public void onBindViewHolder(ViewHolder viewHolder, int pos) {


    if(viewHolder.Holderid ==0)
    {
        // header view
        Log.d("LOG", "in header binder");
        viewHolder.mProductCatalogTitle.setText(mProductHeadingTitle);
        viewHolder.mProductCatalogSubTitle.setText(mProductHeadingSubTitle);
    }
    else if(viewHolder.Holderid==1)
    {
        final int position=pos-1; // -1 to substract header number
        // your code
    }
    else if(viewHolder.Holderid==2)
    {
        // footer
        Log.d("LOG", "in footer binder");
        viewHolder.mProgressBar.setVisibility(visibility);
        viewHolder.mLoading.setText(loadingText);
    }


}

class ViewHolder extends RecyclerView.ViewHolder {

    int Holderid;

    // header
    TextView mProductCatalogTitle;
    TextView mProductCatalogSubTitle;

    //list
    // item type variable declaration

    // footer
    ProgressBar mProgressBar;
    TextView mLoading;

    public ViewHolder(View itemView, int viewType) {
        super(itemView);
        // Here we set the appropriate view in accordance with the the view type as passed when the holder object is created
        if(viewType == TYPE_HEADER)
        {
            Holderid = 0;
            mProductCatalogTitle = (TextView) itemView.findViewById(R.id.tv_title);
            mProductCatalogSubTitle = (TextView) itemView.findViewById(R.id.tv_subtitle);
        }
        else if(viewType == TYPE_ITEM)
        {
            Holderid = 1;
            itemView.setClickable(true);
            itemView.setOnClickListener(new OnClickListener() {
                @Override
                public void onClick(View v) {
                    mCallBack.itemClicked(getAdapterPosition()-1);
                }
            });
            // initialize the view holder
        }

        else if(viewType == TYPE_FOOTER)
        {
            Holderid = 2;
            mLoading = (TextView) itemView.findViewById(R.id.tv_loading);
            mProgressBar = (ProgressBar) itemView.findViewById(R.id.progress_bar);
        }
    }
}

答案 5 :(得分:-1)

对于多个参数

一个简单的功能

function filter(){
    var j = -1; 
    for(var i = 1; i < arguments.length; i++){
        j = arguments[0].indexOf(arguments[i]);
        if(j > -1){
           arguments[0].splice(j, 1);
        }
    }
    return arguments[0];
}

你可以在没有args的情况下调用这个函数 例如:

 filter([1,2,3,4,5,6,7,8,9], 1, 3, 5); //return [2,4,6,7,8,9]
 filter([1,2,3,4,5,6,7,8,9], 1); //return [2,3,4,5,6,7,8,9]

答案 6 :(得分:-1)

这里确实有很好的答案,但是你可以用这种方式做得非常干净,记住你在过滤方法中有一个对象选项可以在回调函数中使用,在这种情况下我会像使用它一样: arguments [i] 所以我可以检查arguments数组中的每个值

function destroyer(arr) {

   for(var i = 1; i < arguments.length; i++){
     arr = arr.filter(isIn, arguments[i]);
   } 

   function isIn(element,index, array){
      if (element != this){
         return element;
      }
   }  
   return arr;
}