Как я могу перебрать этот список сообщений Twitter API? - PullRequest
0 голосов
/ 02 октября 2019

В настоящее время я использую API Twitter, в частности конечную точку https://api.twitter.com/1.1/direct_messages/events/list.json.

То, что возвращает конечная точка, представляет собой массив объектов сообщения.

Объект сообщения выглядит следующим образомпоэтому

{
  target: { recipient_id: '0002' },
  sender_id: '0001',
  source_app_id: '00000',
  message_data: {
    text: 'hello',
    entities: { hashtags: [], symbols: [], user_mentions: [], urls: [] }
  }
}

Исходя из того, что если у меня есть массив этих объектов, я бы использовал цикл for, чтобы сгруппировать сообщения с одинаковым sender_id или receient_id в массив разговоров, а также отслеживать, какой sender_id/ receient_id уже сгруппированы, поэтому у меня нет клонированных бесед с одними и теми же пользователями.

В настоящее время у меня есть двойной цикл for, где первый цикл for захватывает пару sender / receient_id и второй дляцикл проверяет наличие любого другого объекта сообщения с совпадающими идентификаторами, для которых сгруппированы в массив.

То, что я не могу сделать, это отследить, какая пара идентификаторов уже сгруппирована. Я склоняюсь к использованию третьего цикла for, но чувствую, что есть более простое решение.

РЕДАКТИРОВАТЬ: (ДОПОЛНИТЕЛЬНАЯ ИНФОРМАЦИЯ) Это то, что у меня есть в настоящее время.

 // Create conversations array
 convArr = [];

// see what the messages are
for (let i = 0; i < response.data.events.length; i++) {
   // if the next message has same recipient then skip
   sender_id = response.data.events[i].message_create.sender_id;
   recipient_id = 
      response.data.events[i].message_create.target.recipient_id;
   conversation = [];

   // Look for a certain matching sender and recipient id that matches original message
   for (let j = i; j < response.data.events.length; j++) {
      matchedSender = response.data.events[j].message_create.sender_id;
      matchedRecipient = 
      response.data.events[j].message_create.target.recipient_id;
      if((sender_id === matchedSender) | (sender_id === matchedRecipient) 
      &&
      (recipient_id === matchedSender) | (recipient_id === 
  matchedRecipient)) 
      {
     conversation.push(response.data.events[j]);
     } 
    }
   }
  convArr.push(conversation);
}

1 Ответ

0 голосов
/ 02 октября 2019

На основании предоставленной вами информации я думаю, что это можно сделать с помощью одной функции уменьшения. Ключом является создание объекта, ключи которого сначала представляют уникальные разговоры, а затем выводят его в виде массива.

Примерно так:

let messages = [ ... ] // Your messages inside here

// We want to run a reducer on the messages array to get
// unique conversations, then user Object.values to transform
// this back into an array.
let output = Object.values(messages.reduce((acc, message) => {

  // Convert both the sender and receiver ids to numbers.
  let sender = Number(message.sender_id);
  let receiver = Number(message.target.recipient_id);

  // We always want the conversation ID to be the same, regardless
  // of who the sender or receiver was, as long as it's the same
  // participants. The code below will always generate a string with
  // the smaller ID first, and the larger ID second, regardless of 
  // what role the users played in the message.
  let conversation_id = sender > receiver 
    ? `${receiver}_${sender}`
    : `${sender}_${receiver}`;

  if (acc[conversation_id]) {
    // If the conversation already exists, then we will just add this message
    // to the array of messages that make up the conversation
    acc[conversation_id].push(message);
  }
  else {
    // If the conversation doesn't exist, create a new array of messages
    // with this conversation ID and the first message initializing the array.
    acc[conversation_id] = [message];
  }

  // Return the updated accumulator, which will be used in the next
  // iteration.
  return acc;

}, {}));

Пока sender_id и receient_id являются числамиэто должно сработать.

Редактировать

Вот несколько простых объяснений частей, которые могут быть неясными.

Object.values

Эта функция будет работать по-разному в зависимости от того, какой аргумент вы ей предоставляете. Но в основном вы увидите, что это используется для извлечения массива значений из объекта (то есть {}), а не из строки или массива, поскольку у них есть свои собственные методы для этого.

При разговорео значениях объекта, я имею в виду часть значения пар ключ / значение. Например:

let obj = {
  a: 1 // 'a' is the key, 1 is the value
  b: 2 // 'b' is the key, 2 is the value
};

let arrayOfValues = Object.values(obj); // Will return [1, 2]

Array.reduce

Функция уменьшения массива является очень мощным инструментом в арсенале программирования JavaScipt. Он принимает функцию в качестве аргумента и, необязательно, начальное значение для аккумулятора. Это похоже на forEach с состоянием, в котором он выполняет функцию для каждого элемента в массиве, но поддерживает состояние (аккумулятор) на всех итерациях.

Вот простой редуктор ...

let initialState = 'abc';
let values = ['d', 'e', 'f']

let result = values.reduce((acc, val) => {
  return acc + val;
}, initialState);

console.log(result) // 'abcdef';

.. и та же функциональность с простым forEach циклом

let initialState = 'abc';
let values = ['d', 'e', 'f'];
let result = intialState;

values.forEach(value => {
  result += value;
});

console.log(result) // 'abcdef';

Единственное отличие состоит в том, что данные о состоянии, используемые в цикле, содержатся и возвращаются изreduce функция, где, как и во всех других циклах, вам нужно управлять состоянием из области за пределами самого цикла.

ternary operator

Тернарный оператор или что-то подобное существует в большом количестве языков. По сути, это быстрый способ написать оператор if else, целью которого является определение значения одной переменной. Выражение после части ? оператора похоже на if, а выражение после части : похоже на else.

Вот простой троичный символ

let twenty = 20;
let isTwentyGreaterThanTen = twenty > 10 ? 'Yes' : 'No';

console.log(isTwentyGreayerThanTen); // 'Yes'

Аналогичная функциональность с оператором if/else

let twenty = 20;
let isTwentyGreaterThanTen;

if (twenty > 10) {
  isTwentyGreaterThanTen = 'Yes';
}
else {
  isTwentyGreaterThanTen = 'No';
}

console.log(isTwentyGreayerThanTen); // 'Yes'
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...