admin管理员组

文章数量:1134237

Trying to make a function that uses filter but not a for or while loop or foreach function, that will loop through an array of objects only to return their property values. For example,

function getShortMessages(messages) {
    return messages.filter(function(obj){
        return obj.message
    });
}

so if I call

getShortMessages([{message:"bleh"},{message:"blah"}]); 

I should get a return of an array = ["bleh","blah"] I'm just not sure how to implement filter under these guidelines. Also I was thinking of using a chain function maybe .map.

//// Here is the entire code challenge specification/////

Basic: Filter Exercise 4 of 18

Task

Use Array#filter to write a function called getShortMessages.

getShortMessages takes an array of objects with '.message' properties and returns an array of messages that are less than < 50 characters long.

The function should return an array containing the messages themselves, without their containing object.

Arguments

  • messages: an Array of 10 to 100 random objects that look something like this:
{
    message: 'Esse id amet quis eu esse aute officia ipsum.' // random
}

Conditions

  • Do not use any for/while loops or Array#forEach.
  • Do not create any unnecessary functions e.g. helpers.

Hint

  • Try chaining some Array methods!

Example

[ 'Tempor quis esse consequat sunt ea eiusmod.',
  'Id culpa ad proident ad nulla laborum incididunt.',
  'Ullamco in ea et ad anim anim ullamco est.',
  'Est ut irure irure nisi.' ]

Resources

Boilerplate

function getShortMessages(messages) {
  // SOLUTION GOES HERE
}

module.exports = getShortMessages

» To print these instructions again, run: functional-javascript print » To execute your program in a test environment, run: functional-javascript run program.js » To verify your program, run: functional-javascript verify program.js » For help run: functional-javascript help

Trying to make a function that uses filter but not a for or while loop or foreach function, that will loop through an array of objects only to return their property values. For example,

function getShortMessages(messages) {
    return messages.filter(function(obj){
        return obj.message
    });
}

so if I call

getShortMessages([{message:"bleh"},{message:"blah"}]); 

I should get a return of an array = ["bleh","blah"] I'm just not sure how to implement filter under these guidelines. Also I was thinking of using a chain function maybe .map.

//// Here is the entire code challenge specification/////

Basic: Filter Exercise 4 of 18

Task

Use Array#filter to write a function called getShortMessages.

getShortMessages takes an array of objects with '.message' properties and returns an array of messages that are less than < 50 characters long.

The function should return an array containing the messages themselves, without their containing object.

Arguments

  • messages: an Array of 10 to 100 random objects that look something like this:
{
    message: 'Esse id amet quis eu esse aute officia ipsum.' // random
}

Conditions

  • Do not use any for/while loops or Array#forEach.
  • Do not create any unnecessary functions e.g. helpers.

Hint

  • Try chaining some Array methods!

Example

[ 'Tempor quis esse consequat sunt ea eiusmod.',
  'Id culpa ad proident ad nulla laborum incididunt.',
  'Ullamco in ea et ad anim anim ullamco est.',
  'Est ut irure irure nisi.' ]

Resources

  • https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/filter
  • https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map

Boilerplate

function getShortMessages(messages) {
  // SOLUTION GOES HERE
}

module.exports = getShortMessages

» To print these instructions again, run: functional-javascript print » To execute your program in a test environment, run: functional-javascript run program.js » To verify your program, run: functional-javascript verify program.js » For help run: functional-javascript help

Share Improve this question edited Nov 7, 2019 at 9:52 Sasuke Uchiha 4916 silver badges18 bronze badges asked Jul 3, 2015 at 7:40 Jarg7Jarg7 1,6282 gold badges14 silver badges24 bronze badges 5
  • You want .map(), not .filter(). (You might want to read some documentation about .filter().) – nnnnnn Commented Jul 3, 2015 at 7:43
  • thing is, I am doing a javascript code challenge and they are saying I need to use .filter, that is why I am confused. – Jarg7 Commented Jul 3, 2015 at 7:46
  • Either you've misunderstood or their question is wrong. .filter() returns a new array containing elements from the original array. It doesn't transform those elements. – nnnnnn Commented Jul 3, 2015 at 7:47
  • They expect you to use filter to ONLY get messages less than 50 characters or less in length. – Cymen Commented Jul 3, 2015 at 7:49
  • @codemonkey I updated my answer to match the updated question. – Cymen Commented Jul 3, 2015 at 7:56
Add a comment  | 

6 Answers 6

Reset to default 177

Use .filter when you want to get the whole object(s) that match the expected property or properties. Use .map when you have an array of things and want to do some operation on those things and get the result.

The challenge is to get all of the messages that are 50 characters or less. So you can use filter to get only the messages that pass that test and then map to get only the message text.

function getShortMessages(messages) {
  return messages
    .filter(function(obj) {
      return obj.message.length <= 50;
    })
    .map(function(obj) {
      return obj.message;
    });
}

JSFiddle: http://jsfiddle.net/rbbk65sq/

If it is possible for the input objects to not have a message property, you would want to test for it with obj.message && obj.message.length <= 50 like this:

function getShortMessages(messages) {
  return messages
    .filter(function(obj) {
      return obj.message && obj.message.length <= 50;
    })
    .map(function(obj) {
      return obj.message;
    });
}

ES6

The same code samples in ES6:

const getShortMessages = (messages) => messages
  .filter(obj => obj.message.length <= 50)
  .map(obj => obj.message);

And if the input objects might not have the message property:

const getShortMessages = (messages) => messages
  .filter(obj => obj.message && obj.message.length <= 50)
  .map(obj => obj.message);

JSFiddle: http://jsfiddle.net/npfsrwjq/

Though I realize this thread is super old, I felt it necessary to comment in the event that someone stumbles on it again. I would do it like above just using es6 syntax like this:

objects.filter(obj => obj.key === 'value').map(filteredObj => filteredObj.key);

So the above example would be:

getShortMessages = (messages) => messages.filter(obj => obj.message.length <= 50).map(obj => obj.message);

In case someone is looking for a single pass through it can be done with .reduce()

So instead of doing:

const getShortMessages = (messages) => messages
  .filter(obj => obj.message.length <= 50)
  .map(obj => obj.message);

You can do:

const getShortMessages = (messages) => {
  return messages.reduce((shortMessages, i) => {
    if (i.message.length <= 50) {
      shortMessages.push(i.message)
    }
    return shortMessages
  },[])
}

Or if you want even shorter hand:

const getShortMessages = (messages) => messages.reduce((shortMessages, item) => (item.message.length <= 50) 
    ? shortMessages=[...shortMessages,item.message] : shortMessages,[])

With custom return value (Simple ES6 Example);

const customReturnFiltere = (result) => {
    return products.filter((obj) => {
      return obj.stock !== 0;
    })
    .map((finalResult) => {
        return {
          ...finalResult,
          info: 'product will be filtered if stock is 0'
        }
    });
}

In addition, I am using ES6 Destructure with filter and compare two object array. And finally map specific fields those i need actually.

Initialization

const bumperDealRules =[]; // Array object
const cartItems =[]; // Array object

Final code

const bumperDealsSelected = bumperDealRules.filter(
            ({ item_display_id: item_display_id, purchasequantity: purchasequantity }) 
            => cartItems.some(({ id: id, action_from: action_from, order_qty:  order_qty }) 
            => id === item_display_id && purchasequantity <= order_qty &&  action_from == 'bumper_deal' ) 
        ).map(function(obj) {
            return { 
                bumper_deal_company_name_id: obj.bumper_deal_company_name_id, 
                from_amount: obj.from_amount,
                to_amount: obj.to_amount,
                discount: obj.discount,
                highest_limit: obj.highest_limit
             };
          });

All answers are on point, EXCEPT for making the following assumptions:

  1. The messages argument is an array
  2. The array item obj is an object literal. If it is null or undefined you will get a TypeError exception
  3. The obj.message property is a string. Possible scenarios where this is not true:
    1. obj is not an object literal (Number (integer, Float, NaN, Infinity), Array, Function, NaN, Integer, Float, Symbol, etc).
    2. obj doesn't have the message attribute
    3. obj.message is any other data type except string

In the 3.1 and 3.2 scenarios, obj.message is undefined

In the 3.3. scenario, obj.message.length will depend on the obj.message type

Here is a table for the 3.3 scenario showing the length check result for the most common data structures:

obj.message value obj.message.length <= 50
null TypeError
undefined TypeError
Integer (e.g 0, 1, -1) false
Float (e.g. 0.0, 0.1, -0.1) false
Array (<= 50 elements) true
Array (> 50 elements false
Object literal false
Function true
true or false false
NaN false
Infinity or -Infinity false
new Date() false

Table showing only the most common ones.

If your exercise guarantees the data consistency, then it should be fine to follow the above examples.

But in the real world, we should always do defensive coding (and assume that we cannot trust any data provided to us).

Defensive coding solution:

  • Check if the messages is an Array, and handle according to your needs:
    • return []
    • return null
    • throw new TypeError("messages argument should be an array")
  • Check if the array item is not empty
  • Check if the array item.message is a string
  • Check if the array item.message has less than 50 characters
    function getShortMessages(messages) {
      if (!Array.isArray(messages) {
        throw new TypeError("messages argument should be an array")
      }

      return messages
        .filter(function(obj) {
          return (
             !!obj &&
             typeof obj.message === 'string'
             obj.message.length < 50
          );
        })
        .map(function(obj) {
          return obj.message;
        });
    }

ES6

    function getShortMessages(messages) {
      if (!Array.isArray(messages) {
        throw new TypeError("messages argument should be an array")
      }

      return messages
        .filter((obj) => !!obj && typeof obj.message === 'string' && obj.message.length < 50);
        })
        .map((obj) => obj.message );
    }

Final note

If you want to improve as a programmer, you job is to identify the edge cases, and confirm how to handle those scenarios depending on the use case, or the defaults you / your team / your manager / product manager defines.

E.g. what if the obj.message is an empty string '', should you include it or filter it out?

E.g. What if the obj is not an object literal, but an Error, should you include it or filter it out?

    const test = new Error('This is an error with less than 50 characters')
    console.log(test.message.length) // 45

本文标签: javascriptuse filter to return property values in an objectStack Overflow