Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/batch-file/6.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
重新排序Firebase中存储的动态集合/列表中的项目_Firebase_React Redux - Fatal编程技术网

重新排序Firebase中存储的动态集合/列表中的项目

重新排序Firebase中存储的动态集合/列表中的项目,firebase,react-redux,Firebase,React Redux,我目前正在制作一个界面来构建一份调查问卷。问卷中的每个问题都存储在Firebase中,其结构如下: questions | - {key} | - lastModified // <-- When the question was created, last updated | - position // <-- The position in which the question appears on frontend |

我目前正在制作一个界面来构建一份调查问卷。问卷中的每个问题都存储在Firebase中,其结构如下:

questions
   | - {key}
         | - lastModified // <-- When the question was created, last updated
         | - position // <-- The position in which the question appears on frontend
         | - question // <-- Question text content
         | - uid // <-- The unique key with which it is saved to firebase

   /* ... */
   /* Repeat for n questions! */
   /* ... */

但是,有更好的方法吗?

解决这个问题的一种方法是使用浮点数来表示位置,而不是实际的序数整数。然后,当您需要重新订购时,而不是重新保存所有不同的位置,只需在移动的两个项目之间取中点即可

这样,当您删除一个项目时,您可以只保留其他值,因为
位置
是有序的,而不是有序的

示例(项目为字母,位置为数字):


解决这个问题的一种方法是使用浮点数来表示位置,而不是实际的序数整数。然后,当您需要重新订购时,而不是重新保存所有不同的位置,只需在移动的两个项目之间取中点即可

这样,当您删除一个项目时,您可以只保留其他值,因为
位置
是有序的,而不是有序的

示例(项目为字母,位置为数字):


这就是我选择的解决方案。我所做的是:

  • 不再在本地将列表存储为数组(在我的Redux状态中),将其存储为从Firebase提取的对象,在需要修改时将其转换为数组
  • 使用数组时,删除指定的项(我用于此)
  • 映射到数组,使用每个项目的新位置更新它们(使用映射索引)
  • 在将数组推回Firebase之前,将其解析回对象

这是我编写的代码的通用版本,因此可以应用于任何项目列表:

export function removeItem(key, items) {
  return (dispatch) => {

    dispatch({type: REMOVE_ITEM});

    // Convert items object (from state) into an array for easier manipulation
    const itemsArr = items ? Object.keys(items).map(key => items[key]) : [];

    const updatedItems = itemsArr.filter((item) => {
      // Filter out the item that needs to be removed
      return !(item.uid === key);
    }).map((item, index) => {
      // Update new position for remaining items
      return {
        lastModified: item.lastModified,
        position: index,
        content: item.content,
        uid: item.uid
      };
    });

    // Parsing array back into obj before pushing to Firebase
    let updatedItemsObj = {};
    updatedItems.forEach(item => {
      updatedItemsObj[item.uid] = item;
    });
    itemsRef.set(updatedItemsObj)
    .then(() => dispatch(nextAction(...)))
    .catch(error => dispatch(errorAction(key, error)));
  };
}

这就是我选择的解决方案。我所做的是:

  • 不再在本地将列表存储为数组(在我的Redux状态中),将其存储为从Firebase提取的对象,在需要修改时将其转换为数组
  • 使用数组时,删除指定的项(我用于此)
  • 映射到数组,使用每个项目的新位置更新它们(使用映射索引)
  • 在将数组推回Firebase之前,将其解析回对象

这是我编写的代码的通用版本,因此可以应用于任何项目列表:

export function removeItem(key, items) {
  return (dispatch) => {

    dispatch({type: REMOVE_ITEM});

    // Convert items object (from state) into an array for easier manipulation
    const itemsArr = items ? Object.keys(items).map(key => items[key]) : [];

    const updatedItems = itemsArr.filter((item) => {
      // Filter out the item that needs to be removed
      return !(item.uid === key);
    }).map((item, index) => {
      // Update new position for remaining items
      return {
        lastModified: item.lastModified,
        position: index,
        content: item.content,
        uid: item.uid
      };
    });

    // Parsing array back into obj before pushing to Firebase
    let updatedItemsObj = {};
    updatedItems.forEach(item => {
      updatedItemsObj[item.uid] = item;
    });
    itemsRef.set(updatedItemsObj)
    .then(() => dispatch(nextAction(...)))
    .catch(error => dispatch(errorAction(key, error)));
  };
}

这当然会使物品重新定位或移除后的位置保持更简单。谢谢你的建议。我以前见过这种情况,虽然没有使用浮点数,而是使用序数,但数量级为100或10(例如A:10、B:20、C:30)。我现在明白了,浮动的优点是,中点总是可以计算的,相邻定位项目之间的差异可以变得越来越小。但它曾经破裂过吗?我想这取决于你是如何处理浮点精度的?理论上会有一些限制/重新排序的次数,但这需要大量最坏情况下的重新排序才能做到(我认为)。如果达到某个阈值(例如,如果兄弟姐妹相距<0.00001或其他什么),您可以进行某种“重置”,使其重新排序。这当然会使在项目重新定位或移除后保持位置更简单。谢谢你的建议。我以前见过这种情况,虽然没有使用浮点数,而是使用序数,但数量级为100或10(例如A:10、B:20、C:30)。我现在明白了,浮动的优点是,中点总是可以计算的,相邻定位项目之间的差异可以变得越来越小。但它曾经破裂过吗?我想这取决于你是如何处理浮点精度的?理论上会有一些限制/重新排序的次数,但这需要大量最坏情况下的重新排序才能做到(我认为)。如果达到某个阈值(例如,如果兄弟姐妹之间的距离小于0.00001或其他情况),您可以进行某种“重置”,以重新调整它们。
export function removeItem(key, items) {
  return (dispatch) => {

    dispatch({type: REMOVE_ITEM});

    // Convert items object (from state) into an array for easier manipulation
    const itemsArr = items ? Object.keys(items).map(key => items[key]) : [];

    const updatedItems = itemsArr.filter((item) => {
      // Filter out the item that needs to be removed
      return !(item.uid === key);
    }).map((item, index) => {
      // Update new position for remaining items
      return {
        lastModified: item.lastModified,
        position: index,
        content: item.content,
        uid: item.uid
      };
    });

    // Parsing array back into obj before pushing to Firebase
    let updatedItemsObj = {};
    updatedItems.forEach(item => {
      updatedItemsObj[item.uid] = item;
    });
    itemsRef.set(updatedItemsObj)
    .then(() => dispatch(nextAction(...)))
    .catch(error => dispatch(errorAction(key, error)));
  };
}